ia64/linux-2.6.18-xen.hg

changeset 876:bd7e30b58d12

xenbus: Allow lazy init in case xenstored runs in a separate minios domain.

Here's an explanation of the states:

It starts out in XENBUS_XSD_UNCOMMITTED.

As the master xenbus (the one local to xenstored), it will receive an
mmap from xenstore, putting it in XENBUS_XSD_LOCAL_INIT. This enables
the wake_waiting IRQ, which will put it in XENBUS_XSD_LOCAL_READY.

Alternatively, as a slave xenbus, it will receive an ioctl from the
xenstore domain builder, putting it in XENBUS_XSD_FOREIGN_INIT. This
enables the wake_waiting IRQ, which will put it in
XENBUS_XSD_FOREIGN_READY.

DomU's are immediately initialized to XENBUS_XSD_FOREIGN_READY.

Signed-off-by: Diego Ongaro <diego.ongaro@citrix.com>
Signed-off-by: Alex Zeffertt <alex.zeffertt@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue May 19 14:45:50 2009 +0100 (2009-05-19)
parents e17af34d4d90
children f3a935eb30e0
files drivers/xen/core/xen_sysfs.c drivers/xen/xenbus/xenbus_comms.c drivers/xen/xenbus/xenbus_comms.h drivers/xen/xenbus/xenbus_dev.c drivers/xen/xenbus/xenbus_probe.c drivers/xen/xenbus/xenbus_xs.c include/xen/public/xenbus.h
line diff
     1.1 --- a/drivers/xen/core/xen_sysfs.c	Tue May 19 14:42:04 2009 +0100
     1.2 +++ b/drivers/xen/core/xen_sysfs.c	Tue May 19 14:45:50 2009 +0100
     1.3 @@ -16,6 +16,7 @@
     1.4  #include <xen/hypervisor_sysfs.h>
     1.5  #include <xen/xenbus.h>
     1.6  #include <xen/interface/kexec.h>
     1.7 +#include "../xenbus/xenbus_comms.h"
     1.8  
     1.9  MODULE_LICENSE("GPL");
    1.10  MODULE_AUTHOR("Mike D. Day <ncmike@us.ibm.com>");
    1.11 @@ -105,9 +106,8 @@ static ssize_t uuid_show(struct hyp_sysf
    1.12  {
    1.13  	char *vm, *val;
    1.14  	int ret;
    1.15 -	extern int xenstored_ready;
    1.16  
    1.17 -	if (!xenstored_ready)
    1.18 +	if (!is_xenstored_ready())
    1.19  		return -EBUSY;
    1.20  
    1.21  	vm = xenbus_read(XBT_NIL, "vm", "", NULL);
     2.1 --- a/drivers/xen/xenbus/xenbus_comms.c	Tue May 19 14:42:04 2009 +0100
     2.2 +++ b/drivers/xen/xenbus/xenbus_comms.c	Tue May 19 14:45:50 2009 +0100
     2.3 @@ -50,18 +50,39 @@
     2.4  static int xenbus_irq;
     2.5  
     2.6  extern void xenbus_probe(void *);
     2.7 -extern int xenstored_ready;
     2.8  static DECLARE_WORK(probe_work, xenbus_probe, NULL);
     2.9  
    2.10  static DECLARE_WAIT_QUEUE_HEAD(xb_waitq);
    2.11  
    2.12  static irqreturn_t wake_waiting(int irq, void *unused, struct pt_regs *regs)
    2.13  {
    2.14 -	if (unlikely(xenstored_ready == 0)) {
    2.15 -		xenstored_ready = 1;
    2.16 -		schedule_work(&probe_work);
    2.17 +	int old, new;
    2.18 +
    2.19 +	old = atomic_read(&xenbus_xsd_state);
    2.20 +	switch (old) {
    2.21 +		case XENBUS_XSD_UNCOMMITTED:
    2.22 +			BUG();
    2.23 +			return IRQ_HANDLED;
    2.24 +
    2.25 +		case XENBUS_XSD_FOREIGN_INIT:
    2.26 +			new = XENBUS_XSD_FOREIGN_READY;
    2.27 +			break;
    2.28 +		
    2.29 +		case XENBUS_XSD_LOCAL_INIT:
    2.30 +			new = XENBUS_XSD_LOCAL_READY;
    2.31 +			break;
    2.32 +
    2.33 +		case XENBUS_XSD_FOREIGN_READY:
    2.34 +		case XENBUS_XSD_LOCAL_READY:
    2.35 +		default:
    2.36 +			goto wake;
    2.37  	}
    2.38  
    2.39 +	old = atomic_cmpxchg(&xenbus_xsd_state, old, new);
    2.40 +	if (old != new)
    2.41 +		schedule_work(&probe_work);
    2.42 +
    2.43 +wake:
    2.44  	wake_up(&xb_waitq);
    2.45  	return IRQ_HANDLED;
    2.46  }
     3.1 --- a/drivers/xen/xenbus/xenbus_comms.h	Tue May 19 14:42:04 2009 +0100
     3.2 +++ b/drivers/xen/xenbus/xenbus_comms.h	Tue May 19 14:45:50 2009 +0100
     3.3 @@ -43,4 +43,20 @@ int xs_input_avail(void);
     3.4  extern struct xenstore_domain_interface *xen_store_interface;
     3.5  extern int xen_store_evtchn;
     3.6  
     3.7 +/* For xenbus internal use. */
     3.8 +enum {
     3.9 +	XENBUS_XSD_UNCOMMITTED = 0,
    3.10 +	XENBUS_XSD_FOREIGN_INIT,
    3.11 +	XENBUS_XSD_FOREIGN_READY,
    3.12 +	XENBUS_XSD_LOCAL_INIT,
    3.13 +	XENBUS_XSD_LOCAL_READY,
    3.14 +};
    3.15 +extern atomic_t xenbus_xsd_state;
    3.16 +
    3.17 +static inline int is_xenstored_ready(void)
    3.18 +{
    3.19 +	int s = atomic_read(&xenbus_xsd_state);
    3.20 +	return s == XENBUS_XSD_FOREIGN_READY || s == XENBUS_XSD_LOCAL_READY;
    3.21 +}
    3.22 +
    3.23  #endif /* _XENBUS_COMMS_H */
     4.1 --- a/drivers/xen/xenbus/xenbus_dev.c	Tue May 19 14:42:04 2009 +0100
     4.2 +++ b/drivers/xen/xenbus/xenbus_dev.c	Tue May 19 14:45:50 2009 +0100
     4.3 @@ -53,6 +53,8 @@
     4.4  #include <xen/platform-compat.h>
     4.5  #endif
     4.6  
     4.7 +#include <xen/public/xenbus.h>
     4.8 +
     4.9  struct xenbus_dev_transaction {
    4.10  	struct list_head list;
    4.11  	struct xenbus_transaction handle;
    4.12 @@ -96,6 +98,9 @@ static ssize_t xenbus_dev_read(struct fi
    4.13  	struct read_buffer *rb;
    4.14  	int i, ret;
    4.15  
    4.16 +	if (!is_xenstored_ready())
    4.17 +		return -ENODEV;
    4.18 +
    4.19  	mutex_lock(&u->reply_mutex);
    4.20  	while (list_empty(&u->read_buffers)) {
    4.21  		mutex_unlock(&u->reply_mutex);
    4.22 @@ -206,6 +211,9 @@ static ssize_t xenbus_dev_write(struct f
    4.23  	struct watch_adapter *watch, *tmp_watch;
    4.24  	int err, rc = len;
    4.25  
    4.26 +	if (!is_xenstored_ready())
    4.27 +		return -ENODEV;
    4.28 +
    4.29  	if ((len + u->len) > sizeof(u->u.buffer)) {
    4.30  		rc = -EINVAL;
    4.31  		goto out;
    4.32 @@ -370,18 +378,72 @@ static unsigned int xenbus_dev_poll(stru
    4.33  {
    4.34  	struct xenbus_dev_data *u = file->private_data;
    4.35  
    4.36 +	if (!is_xenstored_ready())
    4.37 +		return -ENODEV;
    4.38 +
    4.39  	poll_wait(file, &u->read_waitq, wait);
    4.40  	if (!list_empty(&u->read_buffers))
    4.41  		return POLLIN | POLLRDNORM;
    4.42  	return 0;
    4.43  }
    4.44  
    4.45 +static long xenbus_dev_ioctl(struct file *file,
    4.46 +                             unsigned int cmd, unsigned long data)
    4.47 +{
    4.48 +	extern int xenbus_conn(domid_t remote_dom, int *grant_ref,
    4.49 +	                       evtchn_port_t *local_port);
    4.50 +	void __user *udata = (void __user *) data;
    4.51 +	int ret = -ENOTTY;
    4.52 +	
    4.53 +	if (!is_initial_xendomain())
    4.54 +		return -ENODEV;
    4.55 +
    4.56 +
    4.57 +	switch (cmd) {
    4.58 +	case IOCTL_XENBUS_ALLOC: {
    4.59 +		xenbus_alloc_t xa;
    4.60 +		int old;
    4.61 +
    4.62 +		old = atomic_cmpxchg(&xenbus_xsd_state,
    4.63 +		                     XENBUS_XSD_UNCOMMITTED,
    4.64 +		                     XENBUS_XSD_FOREIGN_INIT);
    4.65 +		if (old != XENBUS_XSD_UNCOMMITTED)
    4.66 +			return -EBUSY;
    4.67 +
    4.68 +		if (copy_from_user(&xa, udata, sizeof(xa))) {
    4.69 +			ret = -EFAULT;
    4.70 +			atomic_set(&xenbus_xsd_state, XENBUS_XSD_UNCOMMITTED);
    4.71 +			break;
    4.72 +		}
    4.73 +
    4.74 +		ret = xenbus_conn(xa.dom, &xa.grant_ref, &xa.port);
    4.75 +		if (ret != 0) {
    4.76 +			atomic_set(&xenbus_xsd_state, XENBUS_XSD_UNCOMMITTED);
    4.77 +			break;
    4.78 +		}
    4.79 +
    4.80 +		if (copy_to_user(udata, &xa, sizeof(xa))) {
    4.81 +			ret = -EFAULT;
    4.82 +			atomic_set(&xenbus_xsd_state, XENBUS_XSD_UNCOMMITTED);
    4.83 +			break;
    4.84 +		}
    4.85 +	}
    4.86 +	break;
    4.87 +
    4.88 +	default:
    4.89 +		break;
    4.90 +	}
    4.91 +
    4.92 +	return ret;
    4.93 +}
    4.94 +
    4.95  static const struct file_operations xenbus_dev_file_ops = {
    4.96  	.read = xenbus_dev_read,
    4.97  	.write = xenbus_dev_write,
    4.98  	.open = xenbus_dev_open,
    4.99  	.release = xenbus_dev_release,
   4.100  	.poll = xenbus_dev_poll,
   4.101 +	.unlocked_ioctl = xenbus_dev_ioctl
   4.102  };
   4.103  
   4.104  int xenbus_dev_init(void)
     5.1 --- a/drivers/xen/xenbus/xenbus_probe.c	Tue May 19 14:42:04 2009 +0100
     5.2 +++ b/drivers/xen/xenbus/xenbus_probe.c	Tue May 19 14:45:50 2009 +0100
     5.3 @@ -44,6 +44,7 @@
     5.4  #include <linux/notifier.h>
     5.5  #include <linux/mutex.h>
     5.6  #include <linux/module.h>
     5.7 +#include <xen/gnttab.h>
     5.8  
     5.9  #include <asm/io.h>
    5.10  #include <asm/page.h>
    5.11 @@ -347,7 +348,12 @@ static void xenbus_dev_shutdown(struct d
    5.12  
    5.13  	DPRINTK("%s", dev->nodename);
    5.14  
    5.15 +/* Commented out since xenstored stubdom is now minios based not linux based
    5.16 +#define XENSTORE_DOMAIN_SHARES_THIS_KERNEL 
    5.17 +*/
    5.18 +#ifndef XENSTORE_DOMAIN_SHARES_THIS_KERNEL 
    5.19  	if (is_initial_xendomain())
    5.20 +#endif
    5.21  		return;
    5.22  
    5.23  	get_device(&dev->dev);
    5.24 @@ -820,14 +826,13 @@ void xenbus_suspend_cancel(void)
    5.25  EXPORT_SYMBOL_GPL(xenbus_suspend_cancel);
    5.26  
    5.27  /* A flag to determine if xenstored is 'ready' (i.e. has started) */
    5.28 -int xenstored_ready = 0;
    5.29 -
    5.30 +atomic_t xenbus_xsd_state = ATOMIC_INIT(XENBUS_XSD_UNCOMMITTED);
    5.31  
    5.32  int register_xenstore_notifier(struct notifier_block *nb)
    5.33  {
    5.34  	int ret = 0;
    5.35  
    5.36 -	if (xenstored_ready > 0)
    5.37 +	if (is_xenstored_ready())
    5.38  		ret = nb->notifier_call(nb, 0, NULL);
    5.39  	else
    5.40  		blocking_notifier_chain_register(&xenstore_chain, nb);
    5.41 @@ -845,7 +850,7 @@ EXPORT_SYMBOL_GPL(unregister_xenstore_no
    5.42  
    5.43  void xenbus_probe(void *unused)
    5.44  {
    5.45 -	BUG_ON((xenstored_ready <= 0));
    5.46 +	BUG_ON(!is_xenstored_ready());
    5.47  
    5.48  	/* Enumerate devices in xenstore and watch for changes. */
    5.49  	xenbus_probe_devices(&xenbus_frontend);
    5.50 @@ -865,6 +870,28 @@ static struct proc_dir_entry *xsd_port_i
    5.51  static int xsd_kva_mmap(struct file *file, struct vm_area_struct *vma)
    5.52  {
    5.53  	size_t size = vma->vm_end - vma->vm_start;
    5.54 +	int old;
    5.55 +	int rc;
    5.56 +
    5.57 +	old = atomic_cmpxchg(&xenbus_xsd_state,
    5.58 +	                   XENBUS_XSD_UNCOMMITTED,
    5.59 +	                   XENBUS_XSD_LOCAL_INIT);
    5.60 +	switch (old) {
    5.61 +		case XENBUS_XSD_UNCOMMITTED:
    5.62 +			rc = xb_init_comms();
    5.63 +			if (rc != 0)
    5.64 +				return rc;
    5.65 +			break;
    5.66 +
    5.67 +		case XENBUS_XSD_FOREIGN_INIT:
    5.68 +		case XENBUS_XSD_FOREIGN_READY:
    5.69 +			return -EBUSY;
    5.70 +		
    5.71 +		case XENBUS_XSD_LOCAL_INIT:
    5.72 +		case XENBUS_XSD_LOCAL_READY:
    5.73 +		default:
    5.74 +			break;
    5.75 +	}
    5.76  
    5.77  	if ((size > PAGE_SIZE) || (vma->vm_pgoff != 0))
    5.78  		return -EINVAL;
    5.79 @@ -897,6 +924,62 @@ static int xsd_port_read(char *page, cha
    5.80  }
    5.81  #endif
    5.82  
    5.83 +static int xb_free_port(evtchn_port_t port)
    5.84 +{
    5.85 +	struct evtchn_close close;
    5.86 +	close.port = port;
    5.87 +	return HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
    5.88 +}
    5.89 +
    5.90 +int xenbus_conn(domid_t remote_dom, unsigned long *grant_ref, evtchn_port_t *local_port)
    5.91 +{
    5.92 +	struct evtchn_alloc_unbound alloc_unbound;
    5.93 +	int rc, rc2;
    5.94 +
    5.95 +	BUG_ON(atomic_read(&xenbus_xsd_state) != XENBUS_XSD_FOREIGN_INIT);
    5.96 +	BUG_ON(!is_initial_xendomain());
    5.97 +
    5.98 +#if defined(CONFIG_PROC_FS) && defined(CONFIG_XEN_PRIVILEGED_GUEST)
    5.99 +	remove_xen_proc_entry("xsd_kva");
   5.100 +	remove_xen_proc_entry("xsd_port");
   5.101 +#endif
   5.102 +
   5.103 +	rc = xb_free_port(xen_store_evtchn);
   5.104 +	if (rc != 0)
   5.105 +		goto fail0;
   5.106 +
   5.107 +	alloc_unbound.dom = DOMID_SELF;
   5.108 +	alloc_unbound.remote_dom = remote_dom;
   5.109 +	rc = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound,
   5.110 +	                                 &alloc_unbound);
   5.111 +	if (rc != 0)
   5.112 +		goto fail0;
   5.113 +	*local_port = xen_store_evtchn = alloc_unbound.port;
   5.114 +
   5.115 +	/* keep the old page (xen_store_mfn, xen_store_interface) */
   5.116 +	rc = gnttab_grant_foreign_access(remote_dom, xen_store_mfn,
   5.117 +	                                 GTF_permit_access);
   5.118 +	if (rc < 0)
   5.119 +		goto fail1;
   5.120 +	*grant_ref = rc;
   5.121 +
   5.122 +	rc = xb_init_comms();
   5.123 +	if (rc != 0)
   5.124 +		goto fail1;
   5.125 +
   5.126 +	return 0;
   5.127 +
   5.128 +fail1:
   5.129 +	rc2 = xb_free_port(xen_store_evtchn);
   5.130 +	if (rc2 != 0)
   5.131 +		printk(KERN_WARNING
   5.132 +		       "XENBUS: Error freeing xenstore event channel: %d\n",
   5.133 +		       rc2);
   5.134 +fail0:
   5.135 +	xen_store_evtchn = -1;
   5.136 +	return rc;
   5.137 +}
   5.138 +
   5.139  static int xenbus_probe_init(void)
   5.140  {
   5.141  	int err = 0;
   5.142 @@ -958,7 +1041,7 @@ static int xenbus_probe_init(void)
   5.143  #endif
   5.144  		xen_store_interface = mfn_to_virt(xen_store_mfn);
   5.145  	} else {
   5.146 -		xenstored_ready = 1;
   5.147 +		atomic_set(&xenbus_xsd_state, XENBUS_XSD_FOREIGN_READY);
   5.148  #ifdef CONFIG_XEN
   5.149  		xen_store_evtchn = xen_start_info->store_evtchn;
   5.150  		xen_store_mfn = xen_start_info->store_mfn;
   5.151 @@ -969,9 +1052,12 @@ static int xenbus_probe_init(void)
   5.152  		xen_store_interface = ioremap(xen_store_mfn << PAGE_SHIFT,
   5.153  					      PAGE_SIZE);
   5.154  #endif
   5.155 +		/* Initialize the shared memory rings to talk to xenstored */
   5.156 +		err = xb_init_comms();
   5.157 +		if (err)
   5.158 +			goto err;
   5.159  	}
   5.160  
   5.161 -
   5.162  	xenbus_dev_init();
   5.163  
   5.164  	/* Initialize the interface to xenstore. */
     6.1 --- a/drivers/xen/xenbus/xenbus_xs.c	Tue May 19 14:42:04 2009 +0100
     6.2 +++ b/drivers/xen/xenbus/xenbus_xs.c	Tue May 19 14:45:50 2009 +0100
     6.3 @@ -872,7 +872,6 @@ static int xenbus_thread(void *unused)
     6.4  
     6.5  int xs_init(void)
     6.6  {
     6.7 -	int err;
     6.8  	struct task_struct *task;
     6.9  
    6.10  	INIT_LIST_HEAD(&xs_state.reply_list);
    6.11 @@ -884,11 +883,6 @@ int xs_init(void)
    6.12  	init_rwsem(&xs_state.transaction_mutex);
    6.13  	init_rwsem(&xs_state.watch_mutex);
    6.14  
    6.15 -	/* Initialize the shared memory rings to talk to xenstored */
    6.16 -	err = xb_init_comms();
    6.17 -	if (err)
    6.18 -		return err;
    6.19 -
    6.20  	task = kthread_run(xenwatch_thread, NULL, "xenwatch");
    6.21  	if (IS_ERR(task))
    6.22  		return PTR_ERR(task);
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/include/xen/public/xenbus.h	Tue May 19 14:45:50 2009 +0100
     7.3 @@ -0,0 +1,56 @@
     7.4 +/******************************************************************************
     7.5 + * xenbus.h
     7.6 + * 
     7.7 + * Interface to /proc/xen/xenbus.
     7.8 + * 
     7.9 + * Copyright (c) 2008, Diego Ongaro <diego.ongaro@citrix.com>
    7.10 + * 
    7.11 + * This program is free software; you can redistribute it and/or
    7.12 + * modify it under the terms of the GNU General Public License version 2
    7.13 + * as published by the Free Software Foundation; or, when distributed
    7.14 + * separately from the Linux kernel or incorporated into other
    7.15 + * software packages, subject to the following license:
    7.16 + * 
    7.17 + * Permission is hereby granted, free of charge, to any person obtaining a copy
    7.18 + * of this source file (the "Software"), to deal in the Software without
    7.19 + * restriction, including without limitation the rights to use, copy, modify,
    7.20 + * merge, publish, distribute, sublicense, and/or sell copies of the Software,
    7.21 + * and to permit persons to whom the Software is furnished to do so, subject to
    7.22 + * the following conditions:
    7.23 + * 
    7.24 + * The above copyright notice and this permission notice shall be included in
    7.25 + * all copies or substantial portions of the Software.
    7.26 + * 
    7.27 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    7.28 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    7.29 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    7.30 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    7.31 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    7.32 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
    7.33 + * IN THE SOFTWARE.
    7.34 + */
    7.35 +
    7.36 +#ifndef __LINUX_PUBLIC_XENBUS_H__
    7.37 +#define __LINUX_PUBLIC_XENBUS_H__
    7.38 +
    7.39 +#include <linux/types.h>
    7.40 +
    7.41 +#ifndef __user
    7.42 +#define __user
    7.43 +#endif
    7.44 +
    7.45 +typedef struct xenbus_alloc {
    7.46 +	domid_t dom;
    7.47 +	__u32 port;
    7.48 +	__u32 grant_ref;
    7.49 +} xenbus_alloc_t;
    7.50 +
    7.51 +/*
    7.52 + * @cmd: IOCTL_XENBUS_ALLOC
    7.53 + * @arg: &xenbus_alloc_t
    7.54 + * Return: 0, or -1 for error
    7.55 + */
    7.56 +#define IOCTL_XENBUS_ALLOC					\
    7.57 +	_IOC(_IOC_NONE, 'X', 0, sizeof(xenbus_alloc_t))
    7.58 +
    7.59 +#endif /* __LINUX_PUBLIC_XENBUS_H__ */