# HG changeset patch
# User sos22@xxxxxxxxxxxxxxxxxxxx
# Node ID 66348ff38ec16b869ac23cd4c92aebde70471414
# Parent 509316987d6596b77b293c4fc162bfd7c60c132a
# Parent 188c782fa9bbde655186380894fb35a89c9ba102
Merge.
Signed-off-by: Steven Smith, sos22@xxxxxxxxx
diff -r 509316987d65 -r 66348ff38ec1
linux-2.6-xen-sparse/arch/xen/kernel/reboot.c
--- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c Fri Aug 19 10:50:15 2005
+++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c Fri Aug 19 13:08:50 2005
@@ -120,8 +120,6 @@
return 0;
}
-extern unsigned uber_debug;
-
static int __do_suspend(void *ignore)
{
int i, j;
@@ -130,13 +128,6 @@
/* Hmmm... a cleaner interface to suspend/resume blkdevs would be nice. */
/* XXX SMH: yes it would :-( */
-#ifdef CONFIG_XEN_BLKDEV_FRONTEND
- extern void blkdev_suspend(void);
- extern void blkdev_resume(void);
-#else
-#define blkdev_suspend() do{}while(0)
-#define blkdev_resume() do{}while(0)
-#endif
#ifdef CONFIG_XEN_NETDEV_FRONTEND
extern void netif_suspend(void);
@@ -234,8 +225,6 @@
netif_suspend();
- blkdev_suspend();
-
time_suspend();
#ifdef CONFIG_SMP
@@ -292,8 +281,6 @@
#endif
time_resume();
-
- blkdev_resume();
netif_resume();
@@ -314,8 +301,6 @@
err = j;
}
}
-
- uber_debug = 0;
out:
if ( suspend_record != NULL )
diff -r 509316987d65 -r 66348ff38ec1
linux-2.6-xen-sparse/drivers/xen/blkback/Makefile
--- a/linux-2.6-xen-sparse/drivers/xen/blkback/Makefile Fri Aug 19 10:50:15 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkback/Makefile Fri Aug 19 13:08:50 2005
@@ -1,2 +1,2 @@
-obj-y := blkback.o control.o interface.o vbd.o
+obj-y := blkback.o xenbus.o interface.o vbd.o
diff -r 509316987d65 -r 66348ff38ec1
linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c Fri Aug 19
10:50:15 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c Fri Aug 19
13:08:50 2005
@@ -104,7 +104,6 @@
#endif
static int do_block_io_op(blkif_t *blkif, int max_to_do);
-static void dispatch_probe(blkif_t *blkif, blkif_request_t *req);
static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req);
static void make_response(blkif_t *blkif, unsigned long id,
unsigned short op, int st);
@@ -349,10 +348,6 @@
dispatch_rw_block_io(blkif, req);
break;
- case BLKIF_OP_PROBE:
- dispatch_probe(blkif, req);
- break;
-
default:
DPRINTK("error: unknown block io operation [%d]\n",
req->operation);
@@ -363,66 +358,6 @@
blk_ring->req_cons = i;
return more_to_do;
-}
-
-static void dispatch_probe(blkif_t *blkif, blkif_request_t *req)
-{
- int rsp = BLKIF_RSP_ERROR;
- int pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)];
-
- /* We expect one buffer only. */
- if ( unlikely(req->nr_segments != 1) )
- goto out;
-
- /* Make sure the buffer is page-sized. */
- if ( (blkif_first_sect(req->frame_and_sects[0]) != 0) ||
- (blkif_last_sect(req->frame_and_sects[0]) != ((PAGE_SIZE/512)-1)) )
- goto out;
-
-#ifdef CONFIG_XEN_BLKDEV_GRANT
- {
- struct gnttab_map_grant_ref map;
-
- map.host_addr = MMAP_VADDR(pending_idx, 0);
- map.flags = GNTMAP_host_map;
- map.ref = blkif_gref_from_fas(req->frame_and_sects[0]);
- map.dom = blkif->domid;
-
- if ( unlikely(HYPERVISOR_grant_table_op(
- GNTTABOP_map_grant_ref, &map, 1)))
- BUG();
-
- if ( map.handle < 0 )
- goto out;
-
- pending_handle(pending_idx, 0) = map.handle;
- }
-#else /* else CONFIG_XEN_BLKDEV_GRANT */
-
-#ifdef CONFIG_XEN_BLKDEV_TAP_BE
- /* Grab the real frontend out of the probe message. */
- if (req->frame_and_sects[1] == BLKTAP_COOKIE)
- blkif->is_blktap = 1;
-#endif
-
-
- if ( HYPERVISOR_update_va_mapping_otherdomain(
- MMAP_VADDR(pending_idx, 0),
- pfn_pte_ma(req->frame_and_sects[0] >> PAGE_SHIFT, PAGE_KERNEL),
-#ifdef CONFIG_XEN_BLKDEV_TAP_BE
- 0, (blkif->is_blktap ? ID_TO_DOM(req->id) : blkif->domid) ) )
-#else
- 0, blkif->domid) )
-#endif
- goto out;
-#endif /* endif CONFIG_XEN_BLKDEV_GRANT */
-
- rsp = vbd_probe(blkif, (vdisk_t *)MMAP_VADDR(pending_idx, 0),
- PAGE_SIZE / sizeof(vdisk_t));
-
- out:
- fast_flush_area(pending_idx, 1);
- make_response(blkif, req->id, req->operation, rsp);
}
static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req)
@@ -460,7 +395,7 @@
goto bad_descriptor;
}
- preq.dev = req->device;
+ preq.dev = req->handle;
preq.sector_number = req->sector_number;
preq.nr_sects = 0;
@@ -730,8 +665,8 @@
0, SLAB_HWCACHE_ALIGN, NULL, NULL);
#endif
- blkif_ctrlif_init();
-
+ blkif_xenbus_init();
+
#ifdef CONFIG_XEN_BLKDEV_GRANT
memset( pending_grant_handles, BLKBACK_INVALID_HANDLE, MMAP_PAGES );
printk(KERN_ALERT "Blkif backend is using grant tables.\n");
diff -r 509316987d65 -r 66348ff38ec1
linux-2.6-xen-sparse/drivers/xen/blkback/common.h
--- a/linux-2.6-xen-sparse/drivers/xen/blkback/common.h Fri Aug 19 10:50:15 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkback/common.h Fri Aug 19 13:08:50 2005
@@ -13,7 +13,6 @@
#include <asm/io.h>
#include <asm/setup.h>
#include <asm/pgalloc.h>
-#include <asm-xen/ctrl_if.h>
#include <asm-xen/evtchn.h>
#include <asm-xen/hypervisor.h>
#include <asm-xen/xen-public/io/blkif.h>
@@ -47,6 +46,7 @@
/* Physical parameters of the comms window. */
unsigned long shmem_frame;
unsigned int evtchn;
+ unsigned int remote_evtchn;
/* Comms information. */
blkif_back_ring_t blk_ring;
/* VBDs attached to this interface. */
@@ -81,17 +81,29 @@
void blkif_connect(blkif_be_connect_t *connect);
int blkif_disconnect(blkif_be_disconnect_t *disconnect, u8 rsp_id);
void blkif_disconnect_complete(blkif_t *blkif);
-blkif_t *blkif_find_by_handle(domid_t domid, unsigned int handle);
+blkif_t *blkif_find(domid_t domid);
+void free_blkif(blkif_t *blkif);
+int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn);
+
#define blkif_get(_b) (atomic_inc(&(_b)->refcnt))
#define blkif_put(_b) \
do { \
if ( atomic_dec_and_test(&(_b)->refcnt) ) \
- blkif_disconnect_complete(_b); \
+ free_blkif(_b); \
} while (0)
-void vbd_create(blkif_be_vbd_create_t *create);
+struct vbd;
+void vbd_free(blkif_t *blkif, struct vbd *vbd);
+
+/* Creates inactive vbd. */
+struct vbd *vbd_create(blkif_t *blkif, blkif_vdev_t vdevice, blkif_pdev_t
pdevice, int readonly);
+int vbd_is_active(struct vbd *vbd);
+void vbd_activate(blkif_t *blkif, struct vbd *vbd);
+
+unsigned long vbd_size(struct vbd *vbd);
+unsigned int vbd_info(struct vbd *vbd);
+unsigned long vbd_secsize(struct vbd *vbd);
void vbd_destroy(blkif_be_vbd_destroy_t *delete);
-int vbd_probe(blkif_t *blkif, vdisk_t *vbd_info, int max_vbds);
void destroy_all_vbds(blkif_t *blkif);
struct phys_req {
@@ -104,9 +116,10 @@
int vbd_translate(struct phys_req *req, blkif_t *blkif, int operation);
void blkif_interface_init(void);
-void blkif_ctrlif_init(void);
void blkif_deschedule(blkif_t *blkif);
+
+void blkif_xenbus_init(void);
irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs);
diff -r 509316987d65 -r 66348ff38ec1
linux-2.6-xen-sparse/drivers/xen/blkback/interface.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c Fri Aug 19
10:50:15 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c Fri Aug 19
13:08:50 2005
@@ -7,24 +7,135 @@
*/
#include "common.h"
+#include <asm-xen/ctrl_if.h>
+#include <asm-xen/evtchn.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
#define VMALLOC_VMADDR(x) ((unsigned long)(x))
#endif
#define BLKIF_HASHSZ 1024
-#define BLKIF_HASH(_d,_h) (((int)(_d)^(int)(_h))&(BLKIF_HASHSZ-1))
+#define BLKIF_HASH(_d) (((int)(_d))&(BLKIF_HASHSZ-1))
static kmem_cache_t *blkif_cachep;
static blkif_t *blkif_hash[BLKIF_HASHSZ];
-blkif_t *blkif_find_by_handle(domid_t domid, unsigned int handle)
-{
- blkif_t *blkif = blkif_hash[BLKIF_HASH(domid, handle)];
- while ( (blkif != NULL) &&
- ((blkif->domid != domid) || (blkif->handle != handle)) )
+blkif_t *blkif_find(domid_t domid)
+{
+ blkif_t *blkif = blkif_hash[BLKIF_HASH(domid)];
+
+ while (blkif) {
+ if (blkif->domid == domid) {
+ blkif_get(blkif);
+ return blkif;
+ }
blkif = blkif->hash_next;
+ }
+
+ blkif = kmem_cache_alloc(blkif_cachep, GFP_KERNEL);
+ if (!blkif)
+ return ERR_PTR(-ENOMEM);
+
+ memset(blkif, 0, sizeof(*blkif));
+ blkif->domid = domid;
+ blkif->status = DISCONNECTED;
+ spin_lock_init(&blkif->vbd_lock);
+ spin_lock_init(&blkif->blk_ring_lock);
+ atomic_set(&blkif->refcnt, 1);
+
+ blkif->hash_next = blkif_hash[BLKIF_HASH(domid)];
+ blkif_hash[BLKIF_HASH(domid)] = blkif;
return blkif;
+}
+
+#ifndef CONFIG_XEN_BLKDEV_GRANT
+static int map_frontend_page(blkif_t *blkif, unsigned long localaddr,
+ unsigned long shared_page)
+{
+ return direct_remap_area_pages(&init_mm, localaddr,
+ shared_page<<PAGE_SHIFT, PAGE_SIZE,
+ __pgprot(_KERNPG_TABLE), blkif->domid);
+}
+
+static void unmap_frontend_page(blkif_t *blkif)
+{
+}
+#else
+static int map_frontend_page(blkif_t *blkif, unsigned long localaddr,
+ unsigned long shared_page)
+{
+ struct gnttab_map_grant_ref op;
+ op.host_addr = localaddr;
+ op.flags = GNTMAP_host_map;
+ op.ref = shared_page;
+ op.dom = blkif->domid;
+
+ BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) );
+
+ if (op.handle < 0) {
+ DPRINTK(" Grant table operation failure !\n");
+ return op.handle;
+ }
+
+ blkif->shmem_ref = shared_page;
+ blkif->shmem_handle = op.handle;
+ blkif->shmem_vaddr = localaddr;
+ return 0;
+}
+
+static void unmap_frontend_page(blkif_t *blkif)
+{
+ struct gnttab_unmap_grant_ref op;
+
+ op.host_addr = blkif->shmem_vaddr;
+ op.handle = blkif->shmem_handle;
+ op.dev_bus_addr = 0;
+ BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
+}
+#endif /* CONFIG_XEN_BLKDEV_GRANT */
+
+int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn)
+{
+ struct vm_struct *vma;
+ blkif_sring_t *sring;
+ evtchn_op_t op = { .cmd = EVTCHNOP_bind_interdomain };
+ int err;
+
+ BUG_ON(blkif->remote_evtchn);
+
+ if ( (vma = get_vm_area(PAGE_SIZE, VM_IOREMAP)) == NULL )
+ return -ENOMEM;
+
+ err = map_frontend_page(blkif, VMALLOC_VMADDR(vma->addr), shared_page);
+ if (err) {
+ vfree(vma->addr);
+ return err;
+ }
+
+ op.u.bind_interdomain.dom1 = DOMID_SELF;
+ op.u.bind_interdomain.dom2 = blkif->domid;
+ op.u.bind_interdomain.port1 = 0;
+ op.u.bind_interdomain.port2 = evtchn;
+ err = HYPERVISOR_event_channel_op(&op);
+ if (err) {
+ unmap_frontend_page(blkif);
+ vfree(vma->addr);
+ return err;
+ }
+
+ blkif->evtchn = op.u.bind_interdomain.port1;
+ blkif->remote_evtchn = evtchn;
+
+ sring = (blkif_sring_t *)vma->addr;
+ SHARED_RING_INIT(sring);
+ BACK_RING_INIT(&blkif->blk_ring, sring, PAGE_SIZE);
+
+ bind_evtchn_to_irqhandler(blkif->evtchn, blkif_be_int, 0, "blkif-backend",
+ blkif);
+ blkif->status = CONNECTED;
+ blkif->shmem_frame = shared_page;
+
+ return 0;
}
static void __blkif_disconnect_complete(void *arg)
@@ -32,21 +143,13 @@
blkif_t *blkif = (blkif_t *)arg;
ctrl_msg_t cmsg;
blkif_be_disconnect_t disc;
-#ifdef CONFIG_XEN_BLKDEV_GRANT
- struct gnttab_unmap_grant_ref op;
-#endif
/*
* These can't be done in blkif_disconnect() because at that point there
* may be outstanding requests at the disc whose asynchronous responses
* must still be notified to the remote driver.
*/
-#ifdef CONFIG_XEN_BLKDEV_GRANT
- op.host_addr = blkif->shmem_vaddr;
- op.handle = blkif->shmem_handle;
- op.dev_bus_addr = 0;
- BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
-#endif
+ unmap_frontend_page(blkif);
vfree(blkif->blk_ring.sring);
/* Construct the deferred response message. */
@@ -81,200 +184,33 @@
schedule_work(&blkif->work);
}
-void blkif_create(blkif_be_create_t *create)
-{
- domid_t domid = create->domid;
- unsigned int handle = create->blkif_handle;
- blkif_t **pblkif, *blkif;
-
- if ( (blkif = kmem_cache_alloc(blkif_cachep, GFP_KERNEL)) == NULL )
+void free_blkif(blkif_t *blkif)
+{
+ blkif_t **pblkif;
+ evtchn_op_t op = { .cmd = EVTCHNOP_close };
+
+ op.u.close.port = blkif->evtchn;
+ op.u.close.dom = DOMID_SELF;
+ HYPERVISOR_event_channel_op(&op);
+ op.u.close.port = blkif->remote_evtchn;
+ op.u.close.dom = blkif->domid;
+ HYPERVISOR_event_channel_op(&op);
+
+ if (blkif->evtchn)
+ unbind_evtchn_from_irqhandler(blkif->evtchn, blkif);
+
+ if (blkif->blk_ring.sring)
+ vfree(blkif->blk_ring.sring);
+
+ pblkif = &blkif_hash[BLKIF_HASH(blkif->domid)];
+ while ( *pblkif != blkif )
{
- DPRINTK("Could not create blkif: out of memory\n");
- create->status = BLKIF_BE_STATUS_OUT_OF_MEMORY;
- return;
- }
-
- memset(blkif, 0, sizeof(*blkif));
- blkif->domid = domid;
- blkif->handle = handle;
- blkif->status = DISCONNECTED;
- spin_lock_init(&blkif->vbd_lock);
- spin_lock_init(&blkif->blk_ring_lock);
- atomic_set(&blkif->refcnt, 0);
-
- pblkif = &blkif_hash[BLKIF_HASH(domid, handle)];
- while ( *pblkif != NULL )
- {
- if ( ((*pblkif)->domid == domid) && ((*pblkif)->handle == handle) )
- {
- DPRINTK("Could not create blkif: already exists\n");
- create->status = BLKIF_BE_STATUS_INTERFACE_EXISTS;
- kmem_cache_free(blkif_cachep, blkif);
- return;
- }
+ BUG_ON(!*pblkif);
pblkif = &(*pblkif)->hash_next;
}
-
- blkif->hash_next = *pblkif;
- *pblkif = blkif;
-
- DPRINTK("Successfully created blkif\n");
- create->status = BLKIF_BE_STATUS_OKAY;
-}
-
-void blkif_destroy(blkif_be_destroy_t *destroy)
-{
- domid_t domid = destroy->domid;
- unsigned int handle = destroy->blkif_handle;
- blkif_t **pblkif, *blkif;
-
- pblkif = &blkif_hash[BLKIF_HASH(domid, handle)];
- while ( (blkif = *pblkif) != NULL )
- {
- if ( (blkif->domid == domid) && (blkif->handle == handle) )
- {
- if ( blkif->status != DISCONNECTED )
- goto still_connected;
- goto destroy;
- }
- pblkif = &blkif->hash_next;
- }
-
- destroy->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND;
- return;
-
- still_connected:
- destroy->status = BLKIF_BE_STATUS_INTERFACE_CONNECTED;
- return;
-
- destroy:
*pblkif = blkif->hash_next;
destroy_all_vbds(blkif);
kmem_cache_free(blkif_cachep, blkif);
- destroy->status = BLKIF_BE_STATUS_OKAY;
-}
-
-void blkif_connect(blkif_be_connect_t *connect)
-{
- domid_t domid = connect->domid;
- unsigned int handle = connect->blkif_handle;
- unsigned int evtchn = connect->evtchn;
- unsigned long shmem_frame = connect->shmem_frame;
- struct vm_struct *vma;
-#ifdef CONFIG_XEN_BLKDEV_GRANT
- int ref = connect->shmem_ref;
-#else
- pgprot_t prot;
- int error;
-#endif
- blkif_t *blkif;
- blkif_sring_t *sring;
-
- blkif = blkif_find_by_handle(domid, handle);
- if ( unlikely(blkif == NULL) )
- {
- DPRINTK("blkif_connect attempted for non-existent blkif (%u,%u)\n",
- connect->domid, connect->blkif_handle);
- connect->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND;
- return;
- }
-
- if ( (vma = get_vm_area(PAGE_SIZE, VM_IOREMAP)) == NULL )
- {
- connect->status = BLKIF_BE_STATUS_OUT_OF_MEMORY;
- return;
- }
-
-#ifndef CONFIG_XEN_BLKDEV_GRANT
- prot = __pgprot(_KERNPG_TABLE);
- error = direct_remap_area_pages(&init_mm, VMALLOC_VMADDR(vma->addr),
- shmem_frame<<PAGE_SHIFT, PAGE_SIZE,
- prot, domid);
- if ( error != 0 )
- {
- if ( error == -ENOMEM )
- connect->status = BLKIF_BE_STATUS_OUT_OF_MEMORY;
- else if ( error == -EFAULT )
- connect->status = BLKIF_BE_STATUS_MAPPING_ERROR;
- else
- connect->status = BLKIF_BE_STATUS_ERROR;
- vfree(vma->addr);
- return;
- }
-#else
- { /* Map: Use the Grant table reference */
- struct gnttab_map_grant_ref op;
- op.host_addr = VMALLOC_VMADDR(vma->addr);
- op.flags = GNTMAP_host_map;
- op.ref = ref;
- op.dom = domid;
-
- BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) );
-
- handle = op.handle;
-
- if (op.handle < 0) {
- DPRINTK(" Grant table operation failure !\n");
- connect->status = BLKIF_BE_STATUS_MAPPING_ERROR;
- vfree(vma->addr);
- return;
- }
-
- blkif->shmem_ref = ref;
- blkif->shmem_handle = handle;
- blkif->shmem_vaddr = VMALLOC_VMADDR(vma->addr);
- }
-#endif
-
- if ( blkif->status != DISCONNECTED )
- {
- connect->status = BLKIF_BE_STATUS_INTERFACE_CONNECTED;
- vfree(vma->addr);
- return;
- }
- sring = (blkif_sring_t *)vma->addr;
- SHARED_RING_INIT(sring);
- BACK_RING_INIT(&blkif->blk_ring, sring, PAGE_SIZE);
-
- blkif->evtchn = evtchn;
- blkif->shmem_frame = shmem_frame;
- blkif->status = CONNECTED;
- blkif_get(blkif);
-
- bind_evtchn_to_irqhandler(
- blkif->evtchn, blkif_be_int, 0, "blkif-backend", blkif);
-
- connect->status = BLKIF_BE_STATUS_OKAY;
-}
-
-int blkif_disconnect(blkif_be_disconnect_t *disconnect, u8 rsp_id)
-{
- domid_t domid = disconnect->domid;
- unsigned int handle = disconnect->blkif_handle;
- blkif_t *blkif;
-
- blkif = blkif_find_by_handle(domid, handle);
- if ( unlikely(blkif == NULL) )
- {
- DPRINTK("blkif_disconnect attempted for non-existent blkif"
- " (%u,%u)\n", disconnect->domid, disconnect->blkif_handle);
- disconnect->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND;
- return 1; /* Caller will send response error message. */
- }
-
- if ( blkif->status == CONNECTED )
- {
- blkif->status = DISCONNECTING;
- blkif->disconnect_rspid = rsp_id;
- wmb(); /* Let other CPUs see the status change. */
- unbind_evtchn_from_irqhandler(blkif->evtchn, blkif);
- blkif_deschedule(blkif);
- blkif_put(blkif);
- return 0; /* Caller should not send response message. */
- }
-
- disconnect->status = BLKIF_BE_STATUS_OKAY;
- return 1;
}
void __init blkif_interface_init(void)
diff -r 509316987d65 -r 66348ff38ec1
linux-2.6-xen-sparse/drivers/xen/blkback/vbd.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkback/vbd.c Fri Aug 19 10:50:15 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkback/vbd.c Fri Aug 19 13:08:50 2005
@@ -11,13 +11,16 @@
*/
#include "common.h"
+#include <asm-xen/xenbus.h>
struct vbd {
- blkif_vdev_t vdevice; /* what the domain refers to this vbd as */
+ blkif_vdev_t handle; /* what the domain refers to this vbd as */
unsigned char readonly; /* Non-zero -> read-only */
unsigned char type; /* VDISK_xxx */
blkif_pdev_t pdevice; /* phys device that this vbd maps to */
struct block_device *bdev;
+
+ int active;
rb_node_t rb; /* for linking into R-B tree lookup struct */
};
@@ -33,140 +36,128 @@
#define bdev_hardsect_size(_b) 512
#endif
-void vbd_create(blkif_be_vbd_create_t *create)
+unsigned long vbd_size(struct vbd *vbd)
+{
+ return vbd_sz(vbd);
+}
+
+unsigned int vbd_info(struct vbd *vbd)
+{
+ return vbd->type | (vbd->readonly?VDISK_READONLY:0);
+}
+
+unsigned long vbd_secsize(struct vbd *vbd)
+{
+ return bdev_hardsect_size(vbd->bdev);
+}
+
+int vbd_is_active(struct vbd *vbd)
+{
+ return vbd->active;
+}
+
+struct vbd *vbd_create(blkif_t *blkif, blkif_vdev_t handle,
+ blkif_pdev_t pdevice, int readonly)
{
struct vbd *vbd;
+
+ if ( unlikely((vbd = kmalloc(sizeof(struct vbd), GFP_KERNEL)) == NULL) )
+ {
+ DPRINTK("vbd_create: out of memory\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ vbd->handle = handle;
+ vbd->readonly = readonly;
+ vbd->type = 0;
+ vbd->active = 0;
+
+ vbd->pdevice = pdevice;
+
+ /* FIXME: Who frees vbd on failure? --RR */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ vbd->bdev = open_by_devnum(
+ vbd_map_devnum(vbd->pdevice),
+ vbd->readonly ? FMODE_READ : FMODE_WRITE);
+ if ( IS_ERR(vbd->bdev) )
+ {
+ DPRINTK("vbd_creat: device %08x doesn't exist.\n", vbd->pdevice);
+ return ERR_PTR(-ENOENT);
+ }
+
+ if ( (vbd->bdev->bd_disk == NULL) )
+ {
+ DPRINTK("vbd_creat: device %08x doesn't exist.\n", vbd->pdevice);
+ bdev_put(vbd->bdev);
+ return ERR_PTR(-ENOENT);
+ }
+
+ if ( vbd->bdev->bd_disk->flags & GENHD_FL_CD )
+ vbd->type |= VDISK_CDROM;
+ if ( vbd->bdev->bd_disk->flags & GENHD_FL_REMOVABLE )
+ vbd->type |= VDISK_REMOVABLE;
+
+#else
+ if ( (blk_size[MAJOR(vbd->pdevice)] == NULL) || (vbd_sz(vbd) == 0) )
+ {
+ DPRINTK("vbd_creat: device %08x doesn't exist.\n", vbd->pdevice);
+ return ERR_PTR(-ENOENT);
+ }
+#endif
+
+ DPRINTK("Successful creation of handle=%04x (dom=%u)\n",
+ handle, blkif->domid);
+ return vbd;
+}
+
+void vbd_activate(blkif_t *blkif, struct vbd *vbd)
+{
rb_node_t **rb_p, *rb_parent = NULL;
- blkif_t *blkif;
- blkif_vdev_t vdevice = create->vdevice;
-
- blkif = blkif_find_by_handle(create->domid, create->blkif_handle);
- if ( unlikely(blkif == NULL) )
- {
- DPRINTK("vbd_create attempted for non-existent blkif (%u,%u)\n",
- create->domid, create->blkif_handle);
- create->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND;
- return;
- }
-
+ struct vbd *i;
+ BUG_ON(vbd_is_active(vbd));
+
+ /* Find where to put it. */
rb_p = &blkif->vbd_rb.rb_node;
while ( *rb_p != NULL )
{
rb_parent = *rb_p;
- vbd = rb_entry(rb_parent, struct vbd, rb);
- if ( vdevice < vbd->vdevice )
+ i = rb_entry(rb_parent, struct vbd, rb);
+ if ( vbd->handle < i->handle )
{
rb_p = &rb_parent->rb_left;
}
- else if ( vdevice > vbd->vdevice )
+ else if ( vbd->handle > i->handle )
{
rb_p = &rb_parent->rb_right;
}
else
{
- DPRINTK("vbd_create attempted for already existing vbd\n");
- create->status = BLKIF_BE_STATUS_VBD_EXISTS;
- return;
+ /* We never create two of same vbd, so not possible. */
+ BUG();
}
}
- if ( unlikely((vbd = kmalloc(sizeof(struct vbd), GFP_KERNEL)) == NULL) )
- {
- DPRINTK("vbd_create: out of memory\n");
- create->status = BLKIF_BE_STATUS_OUT_OF_MEMORY;
- return;
- }
-
- vbd->vdevice = vdevice;
- vbd->readonly = create->readonly;
- vbd->type = 0;
-
- /* Mask to 16-bit for compatibility with old tools */
- vbd->pdevice = create->pdevice & 0xffff;
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- vbd->bdev = open_by_devnum(
- vbd_map_devnum(vbd->pdevice),
- vbd->readonly ? FMODE_READ : FMODE_WRITE);
- if ( IS_ERR(vbd->bdev) )
- {
- DPRINTK("vbd_creat: device %08x doesn't exist.\n", vbd->pdevice);
- create->status = BLKIF_BE_STATUS_PHYSDEV_NOT_FOUND;
- return;
- }
-
- if ( (vbd->bdev->bd_disk == NULL) )
- {
- DPRINTK("vbd_creat: device %08x doesn't exist.\n", vbd->pdevice);
- create->status = BLKIF_BE_STATUS_PHYSDEV_NOT_FOUND;
- bdev_put(vbd->bdev);
- return;
- }
-
- if ( vbd->bdev->bd_disk->flags & GENHD_FL_CD )
- vbd->type |= VDISK_CDROM;
- if ( vbd->bdev->bd_disk->flags & GENHD_FL_REMOVABLE )
- vbd->type |= VDISK_REMOVABLE;
-
-#else
- if ( (blk_size[MAJOR(vbd->pdevice)] == NULL) || (vbd_sz(vbd) == 0) )
- {
- DPRINTK("vbd_creat: device %08x doesn't exist.\n", vbd->pdevice);
- create->status = BLKIF_BE_STATUS_PHYSDEV_NOT_FOUND;
- return;
- }
-#endif
+ /* Now we're active. */
+ vbd->active = 1;
+ blkif_get(blkif);
spin_lock(&blkif->vbd_lock);
rb_link_node(&vbd->rb, rb_parent, rb_p);
rb_insert_color(&vbd->rb, &blkif->vbd_rb);
spin_unlock(&blkif->vbd_lock);
-
- DPRINTK("Successful creation of vdev=%04x (dom=%u)\n",
- vdevice, create->domid);
- create->status = BLKIF_BE_STATUS_OKAY;
-}
-
-
-void vbd_destroy(blkif_be_vbd_destroy_t *destroy)
-{
- blkif_t *blkif;
- struct vbd *vbd;
- rb_node_t *rb;
- blkif_vdev_t vdevice = destroy->vdevice;
-
- blkif = blkif_find_by_handle(destroy->domid, destroy->blkif_handle);
- if ( unlikely(blkif == NULL) )
- {
- DPRINTK("vbd_destroy attempted for non-existent blkif (%u,%u)\n",
- destroy->domid, destroy->blkif_handle);
- destroy->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND;
- return;
- }
-
- rb = blkif->vbd_rb.rb_node;
- while ( rb != NULL )
- {
- vbd = rb_entry(rb, struct vbd, rb);
- if ( vdevice < vbd->vdevice )
- rb = rb->rb_left;
- else if ( vdevice > vbd->vdevice )
- rb = rb->rb_right;
- else
- goto found;
- }
-
- destroy->status = BLKIF_BE_STATUS_VBD_NOT_FOUND;
- return;
-
- found:
- spin_lock(&blkif->vbd_lock);
- rb_erase(rb, &blkif->vbd_rb);
- spin_unlock(&blkif->vbd_lock);
+}
+
+void vbd_free(blkif_t *blkif, struct vbd *vbd)
+{
+ if (vbd_is_active(vbd)) {
+ spin_lock(&blkif->vbd_lock);
+ rb_erase(&vbd->rb, &blkif->vbd_rb);
+ spin_unlock(&blkif->vbd_lock);
+ blkif_put(blkif);
+ }
bdev_put(vbd->bdev);
kfree(vbd);
}
-
void destroy_all_vbds(blkif_t *blkif)
{
@@ -183,73 +174,11 @@
bdev_put(vbd->bdev);
kfree(vbd);
spin_lock(&blkif->vbd_lock);
+ blkif_put(blkif);
}
spin_unlock(&blkif->vbd_lock);
}
-
-
-static void vbd_probe_single(
- blkif_t *blkif, vdisk_t *vbd_info, struct vbd *vbd)
-{
- vbd_info->device = vbd->vdevice;
- vbd_info->info = vbd->type | (vbd->readonly ? VDISK_READONLY : 0);
- vbd_info->capacity = vbd_sz(vbd);
- vbd_info->sector_size = bdev_hardsect_size(vbd->bdev);
-}
-
-
-int vbd_probe(blkif_t *blkif, vdisk_t *vbd_info, int max_vbds)
-{
- int rc = 0, nr_vbds = 0;
- rb_node_t *rb;
-
- spin_lock(&blkif->vbd_lock);
-
- if ( (rb = blkif->vbd_rb.rb_node) == NULL )
- goto out;
-
- new_subtree:
- /* STEP 1. Find least node (it'll be left-most). */
- while ( rb->rb_left != NULL )
- rb = rb->rb_left;
-
- for ( ; ; )
- {
- /* STEP 2. Dealt with left subtree. Now process current node. */
- vbd_probe_single(blkif, &vbd_info[nr_vbds],
- rb_entry(rb, struct vbd, rb));
- if ( ++nr_vbds == max_vbds )
- goto out;
-
- /* STEP 3. Process right subtree, if any. */
- if ( rb->rb_right != NULL )
- {
- rb = rb->rb_right;
- goto new_subtree;
- }
-
- /* STEP 4. Done both subtrees. Head back through ancesstors. */
- for ( ; ; )
- {
- /* We're done when we get back to the root node. */
- if ( rb->rb_parent == NULL )
- goto out;
- /* If we are left of parent, then parent is next to process. */
- if ( rb->rb_parent->rb_left == rb )
- break;
- /* If we are right of parent, then we climb to grandparent. */
- rb = rb->rb_parent;
- }
-
- rb = rb->rb_parent;
- }
-
- out:
- spin_unlock(&blkif->vbd_lock);
- return (rc == 0) ? nr_vbds : rc;
-}
-
int vbd_translate(struct phys_req *req, blkif_t *blkif, int operation)
{
@@ -264,9 +193,9 @@
while ( rb != NULL )
{
vbd = rb_entry(rb, struct vbd, rb);
- if ( req->dev < vbd->vdevice )
+ if ( req->dev < vbd->handle )
rb = rb->rb_left;
- else if ( req->dev > vbd->vdevice )
+ else if ( req->dev > vbd->handle )
rb = rb->rb_right;
else
goto found;
diff -r 509316987d65 -r 66348ff38ec1
linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Fri Aug 19
10:50:15 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Fri Aug 19
13:08:50 2005
@@ -53,8 +53,8 @@
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <scsi/scsi.h>
-#include <asm-xen/ctrl_if.h>
#include <asm-xen/evtchn.h>
+#include <asm-xen/xenbus.h>
#ifdef CONFIG_XEN_BLKDEV_GRANT
#include <asm-xen/xen-public/grant_table.h>
#include <asm-xen/gnttab.h>
@@ -65,22 +65,14 @@
/* Control whether runtime update of vbds is enabled. */
#define ENABLE_VBD_UPDATE 1
-#if ENABLE_VBD_UPDATE
-static void vbd_update(void);
-#else
-static void vbd_update(void){};
-#endif
-
#define BLKIF_STATE_CLOSED 0
#define BLKIF_STATE_DISCONNECTED 1
#define BLKIF_STATE_CONNECTED 2
-static int blkif_handle = 0;
static unsigned int blkif_state = BLKIF_STATE_CLOSED;
static unsigned int blkif_evtchn = 0;
-
-static int blkif_control_rsp_valid;
-static blkif_response_t blkif_control_rsp;
+static unsigned int blkif_vbds = 0;
+static unsigned int blkif_vbds_connected = 0;
static blkif_front_ring_t blk_ring;
@@ -92,6 +84,7 @@
#define MAXIMUM_OUTSTANDING_BLOCK_REQS \
(BLKIF_MAX_SEGMENTS_PER_REQUEST * BLKIF_RING_SIZE)
#define GRANTREF_INVALID (1<<15)
+static int shmem_ref;
#endif
static struct blk_shadow {
@@ -105,7 +98,7 @@
static void kick_pending_request_queues(void);
-int __init xlblk_init(void);
+static int __init xlblk_init(void);
static void blkif_completion(struct blk_shadow *s);
@@ -179,19 +172,6 @@
module_init(xlblk_init);
-#if ENABLE_VBD_UPDATE
-static void update_vbds_task(void *unused)
-{
- xlvbd_update_vbds();
-}
-
-static void vbd_update(void)
-{
- static DECLARE_WORK(update_tq, update_vbds_task, NULL);
- schedule_work(&update_tq);
-}
-#endif /* ENABLE_VBD_UPDATE */
-
static struct xlbd_disk_info *head_waiting = NULL;
static void kick_pending_request_queues(void)
{
@@ -221,16 +201,7 @@
int blkif_release(struct inode *inode, struct file *filep)
{
- struct gendisk *gd = inode->i_bdev->bd_disk;
- struct xlbd_disk_info *di = (struct xlbd_disk_info *)gd->private_data;
-
- /*
- * When usage drops to zero it may allow more VBD updates to occur.
- * Update of usage count is protected by a per-device semaphore.
- */
- if ( --di->mi->usage == 0 )
- vbd_update();
-
+ /* FIXME: This is where we can actually free up majors, etc. --RR */
return 0;
}
@@ -301,7 +272,7 @@
ring_req->operation = rq_data_dir(req) ? BLKIF_OP_WRITE :
BLKIF_OP_READ;
ring_req->sector_number = (blkif_sector_t)req->sector;
- ring_req->device = di->xd_device;
+ ring_req->handle = di->handle;
ring_req->nr_segments = 0;
rq_for_each_bio(bio, req)
@@ -446,10 +417,6 @@
end_that_request_last(req);
break;
- case BLKIF_OP_PROBE:
- memcpy(&blkif_control_rsp, bret, sizeof(*bret));
- blkif_control_rsp_valid = 1;
- break;
default:
BUG();
}
@@ -483,28 +450,6 @@
#define blkif_io_lock io_request_lock
/*============================================================================*/
-#if ENABLE_VBD_UPDATE
-
-/*
- * blkif_update_int/update-vbds_task - handle VBD update events.
- * Schedule a task for keventd to run, which will update the VBDs and perform
- * the corresponding updates to our view of VBD state.
- */
-static void update_vbds_task(void *unused)
-{
- xlvbd_update_vbds();
-}
-
-static void vbd_update(void)
-{
- static struct tq_struct update_tq;
- update_tq.routine = update_vbds_task;
- schedule_task(&update_tq);
-}
-
-#endif /* ENABLE_VBD_UPDATE */
-/*============================================================================*/
-
static void kick_pending_request_queues(void)
{
/* We kick pending request queues if the ring is reasonably empty. */
@@ -757,7 +702,8 @@
char * buffer,
unsigned long sector_number,
unsigned short nr_sectors,
- kdev_t device)
+ kdev_t device,
+ blkif_vdev_t handle)
{
unsigned long buffer_ma = virt_to_bus(buffer);
unsigned long xid;
@@ -871,7 +817,7 @@
req->id = xid;
req->operation = operation;
req->sector_number = (blkif_sector_t)sector_number;
- req->device = device;
+ req->handle = handle;
req->nr_segments = 1;
#ifdef CONFIG_XEN_BLKDEV_GRANT
/* install a grant reference. */
@@ -1047,108 +993,10 @@
/***************************** COMMON CODE *******************************/
-#ifdef CONFIG_XEN_BLKDEV_GRANT
-void blkif_control_probe_send(blkif_request_t *req, blkif_response_t *rsp,
- unsigned long address)
-{
- int ref = gnttab_claim_grant_reference(&gref_head, gref_terminal);
- ASSERT( ref != -ENOSPC );
-
- gnttab_grant_foreign_access_ref( ref, rdomid, address >> PAGE_SHIFT, 0 );
-
- req->frame_and_sects[0] = blkif_fas_from_gref(ref, 0, (PAGE_SIZE/512)-1);
-
- blkif_control_send(req, rsp);
-}
-#endif
-
-void blkif_control_send(blkif_request_t *req, blkif_response_t *rsp)
-{
- unsigned long flags, id;
- blkif_request_t *req_d;
-
- retry:
- while ( RING_FULL(&blk_ring) )
- {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
-
- spin_lock_irqsave(&blkif_io_lock, flags);
- if ( RING_FULL(&blk_ring) )
- {
- spin_unlock_irqrestore(&blkif_io_lock, flags);
- goto retry;
- }
-
- DISABLE_SCATTERGATHER();
- req_d = RING_GET_REQUEST(&blk_ring, blk_ring.req_prod_pvt);
- *req_d = *req;
-
- id = GET_ID_FROM_FREELIST();
- req_d->id = id;
- blk_shadow[id].request = (unsigned long)req;
-
- pickle_request(&blk_shadow[id], req);
-
- blk_ring.req_prod_pvt++;
- flush_requests();
-
- spin_unlock_irqrestore(&blkif_io_lock, flags);
-
- while ( !blkif_control_rsp_valid )
- {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
-
- memcpy(rsp, &blkif_control_rsp, sizeof(*rsp));
- blkif_control_rsp_valid = 0;
-}
-
-
-/* Send a driver status notification to the domain controller. */
-static void send_driver_status(int ok)
-{
- ctrl_msg_t cmsg = {
- .type = CMSG_BLKIF_FE,
- .subtype = CMSG_BLKIF_FE_DRIVER_STATUS,
- .length = sizeof(blkif_fe_driver_status_t),
- };
- blkif_fe_driver_status_t *msg = (void*)cmsg.msg;
-
- msg->status = (ok ? BLKIF_DRIVER_STATUS_UP : BLKIF_DRIVER_STATUS_DOWN);
-
- ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
-}
-
-/* Tell the controller to bring up the interface. */
-static void blkif_send_interface_connect(void)
-{
- ctrl_msg_t cmsg = {
- .type = CMSG_BLKIF_FE,
- .subtype = CMSG_BLKIF_FE_INTERFACE_CONNECT,
- .length = sizeof(blkif_fe_interface_connect_t),
- };
- blkif_fe_interface_connect_t *msg = (void*)cmsg.msg;
-
- msg->handle = 0;
- msg->shmem_frame = (virt_to_machine(blk_ring.sring) >> PAGE_SHIFT);
-
-#ifdef CONFIG_XEN_BLKDEV_GRANT
- msg->shmem_ref = gnttab_claim_grant_reference( &gref_head, gref_terminal
);
- ASSERT( msg->shmem_ref != -ENOSPC );
- gnttab_grant_foreign_access_ref ( msg->shmem_ref , rdomid,
msg->shmem_frame, 0 );
-#endif
-
- ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
-}
-
static void blkif_free(void)
{
/* Prevent new requests being issued until we fix things up. */
spin_lock_irq(&blkif_io_lock);
- recovery = 1;
blkif_state = BLKIF_STATE_DISCONNECTED;
spin_unlock_irq(&blkif_io_lock);
@@ -1160,31 +1008,6 @@
}
unbind_evtchn_from_irqhandler(blkif_evtchn, NULL);
blkif_evtchn = 0;
-}
-
-static void blkif_close(void)
-{
-}
-
-/* Move from CLOSED to DISCONNECTED state. */
-static void blkif_disconnect(void)
-{
- blkif_sring_t *sring;
-
- if ( blk_ring.sring != NULL )
- free_page((unsigned long)blk_ring.sring);
-
- sring = (blkif_sring_t *)__get_free_page(GFP_KERNEL);
- SHARED_RING_INIT(sring);
- FRONT_RING_INIT(&blk_ring, sring, PAGE_SIZE);
- blkif_state = BLKIF_STATE_DISCONNECTED;
- blkif_send_interface_connect();
-}
-
-static void blkif_reset(void)
-{
- blkif_free();
- blkif_disconnect();
}
static void blkif_recover(void)
@@ -1257,11 +1080,14 @@
blkif_state = BLKIF_STATE_CONNECTED;
}
-static void blkif_connect(blkif_fe_interface_status_t *status)
+static void blkif_connect(u16 evtchn, domid_t domid)
{
int err = 0;
- blkif_evtchn = status->evtchn;
+ blkif_evtchn = evtchn;
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+ rdomid = domid;
+#endif
err = bind_evtchn_to_irqhandler(
blkif_evtchn, blkif_int, SA_SAMPLE_RANDOM, "blkif", NULL);
@@ -1270,142 +1096,318 @@
WPRINTK("bind_evtchn_to_irqhandler failed (err=%d)\n", err);
return;
}
-
- if ( recovery )
- {
- blkif_recover();
- }
- else
- {
- /* Transition to connected in case we need to do
- * a partition probe on a whole disk. */
- blkif_state = BLKIF_STATE_CONNECTED;
-
- /* Probe for discs attached to the interface. */
- xlvbd_init();
- }
-
- /* Kick pending requests. */
- spin_lock_irq(&blkif_io_lock);
- kick_pending_request_queues();
- spin_unlock_irq(&blkif_io_lock);
-}
-
-static void unexpected(blkif_fe_interface_status_t *status)
-{
- DPRINTK(" Unexpected blkif status %u in state %u\n",
- status->status, blkif_state);
-}
-
-static void blkif_status(blkif_fe_interface_status_t *status)
-{
+}
+
+
+static struct xenbus_device_id blkfront_ids[] = {
+ { "vbd" },
+ { "" }
+};
+
+struct blkfront_info
+{
+ /* We watch the backend */
+ struct xenbus_watch watch;
+ int vdevice;
+ u16 handle;
+ int connected;
+ struct xenbus_device *dev;
+ char *backend;
+};
+
+static void watch_for_status(struct xenbus_watch *watch, const char *node)
+{
+ struct blkfront_info *info;
+ unsigned int binfo;
+ unsigned long sectors, sector_size;
+ int err;
+
+ info = container_of(watch, struct blkfront_info, watch);
+ node += strlen(watch->node);
+
+ /* FIXME: clean up when error on the other end. */
+ if (info->connected)
+ return;
+
+ err = xenbus_gather(watch->node,
+ "sectors", "%lu", §ors,
+ "info", "%u", &binfo,
+ "sector-size", "%lu", §or_size,
+ NULL);
+
+ if (err)
+ xenbus_dev_error(info->dev, err, "reading backend fields");
+ else {
+ xlvbd_add(sectors, info->vdevice, info->handle, binfo,
+ sector_size);
+ info->connected = 1;
+
+ /* First to connect? blkif is now connected. */
+ if (blkif_vbds_connected++ == 0)
+ blkif_state = BLKIF_STATE_CONNECTED;
+
+ xenbus_dev_ok(info->dev);
+
+ /* Kick pending requests. */
+ spin_lock_irq(&blkif_io_lock);
+ kick_pending_request_queues();
+ spin_unlock_irq(&blkif_io_lock);
+ }
+}
+
+static int setup_blkring(struct xenbus_device *dev, unsigned int backend_id)
+{
+ blkif_sring_t *sring;
+ evtchn_op_t op = { .cmd = EVTCHNOP_alloc_unbound };
+ int err;
+
+ sring = (void *)__get_free_page(GFP_KERNEL);
+ if (!sring) {
+ xenbus_dev_error(dev, -ENOMEM, "allocating shared ring");
+ return -ENOMEM;
+ }
+ SHARED_RING_INIT(sring);
+ FRONT_RING_INIT(&blk_ring, sring, PAGE_SIZE);
+
#ifdef CONFIG_XEN_BLKDEV_GRANT
- rdomid = status->domid; /* need to set rdomid early */
-#endif
-
- if ( status->handle != blkif_handle )
- {
- WPRINTK(" Invalid blkif: handle=%u\n", status->handle);
- unexpected(status);
- return;
- }
-
- switch ( status->status )
- {
- case BLKIF_INTERFACE_STATUS_CLOSED:
- switch ( blkif_state )
- {
- case BLKIF_STATE_CLOSED:
- unexpected(status);
- break;
- case BLKIF_STATE_DISCONNECTED:
- case BLKIF_STATE_CONNECTED:
- unexpected(status);
- blkif_close();
- break;
- }
- break;
-
- case BLKIF_INTERFACE_STATUS_DISCONNECTED:
- switch ( blkif_state )
- {
- case BLKIF_STATE_CLOSED:
- blkif_disconnect();
- break;
- case BLKIF_STATE_DISCONNECTED:
- case BLKIF_STATE_CONNECTED:
- /* unexpected(status); */ /* occurs during suspend/resume */
- blkif_reset();
- break;
- }
- break;
-
- case BLKIF_INTERFACE_STATUS_CONNECTED:
- switch ( blkif_state )
- {
- case BLKIF_STATE_CLOSED:
- unexpected(status);
- blkif_disconnect();
- blkif_connect(status);
- break;
- case BLKIF_STATE_DISCONNECTED:
- blkif_connect(status);
- break;
- case BLKIF_STATE_CONNECTED:
- unexpected(status);
- blkif_connect(status);
- break;
- }
- break;
-
- case BLKIF_INTERFACE_STATUS_CHANGED:
- switch ( blkif_state )
- {
- case BLKIF_STATE_CLOSED:
- case BLKIF_STATE_DISCONNECTED:
- unexpected(status);
- break;
- case BLKIF_STATE_CONNECTED:
- vbd_update();
- break;
- }
- break;
-
- default:
- WPRINTK(" Invalid blkif status: %d\n", status->status);
- break;
- }
-}
-
-
-static void blkif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
-{
- switch ( msg->subtype )
- {
- case CMSG_BLKIF_FE_INTERFACE_STATUS:
- blkif_status((blkif_fe_interface_status_t *)
- &msg->msg[0]);
- break;
- default:
- msg->length = 0;
- break;
- }
-
- ctrl_if_send_response(msg);
-}
-
-int wait_for_blkif(void)
+ shmem_ref = gnttab_claim_grant_reference(&gref_head,
+ gref_terminal);
+ ASSERT(shmem_ref != -ENOSPC);
+ gnttab_grant_foreign_access_ref(shmem_ref,
+ backend_id,
+ virt_to_machine(blk_ring.sring)
+ >> PAGE_SHIFT, 0);
+#endif
+
+ op.u.alloc_unbound.dom = backend_id;
+ err = HYPERVISOR_event_channel_op(&op);
+ if (err) {
+ free_page((unsigned long)blk_ring.sring);
+ blk_ring.sring = 0;
+ xenbus_dev_error(dev, err, "allocating event channel");
+ return err;
+ }
+ blkif_connect(op.u.alloc_unbound.port, backend_id);
+ return 0;
+}
+
+/* Common code used when first setting up, and when resuming. */
+static int talk_to_backend(struct xenbus_device *dev,
+ struct blkfront_info *info)
+{
+ char *backend;
+ const char *message;
+ int err, backend_id;
+
+ backend = xenbus_read(dev->nodename, "backend", NULL);
+ if (IS_ERR(backend)) {
+ err = PTR_ERR(backend);
+ if (err == -ENOENT)
+ goto out;
+ xenbus_dev_error(dev, err, "reading %s/backend",
+ dev->nodename);
+ goto out;
+ }
+ if (strlen(backend) == 0) {
+ err = -ENOENT;
+ goto free_backend;
+ }
+
+ /* FIXME: This driver can't handle backends on different
+ * domains. Check and fail gracefully. */
+ err = xenbus_scanf(dev->nodename, "backend-id", "%i", &backend_id);
+ if (err == -ENOENT)
+ goto free_backend;
+ if (err < 0) {
+ xenbus_dev_error(dev, err, "reading %s/backend-id",
+ dev->nodename);
+ goto free_backend;
+ }
+
+ /* First device? We create shared ring, alloc event channel. */
+ if (blkif_vbds == 0) {
+ err = setup_blkring(dev, backend_id);
+ if (err)
+ goto free_backend;
+ }
+
+ err = xenbus_transaction_start(dev->nodename);
+ if (err) {
+ xenbus_dev_error(dev, err, "starting transaction");
+ goto destroy_blkring;
+ }
+
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+ err = xenbus_printf(dev->nodename, "grant-id","%u", shmem_ref);
+ if (err) {
+ message = "writing grant-id";
+ goto abort_transaction;
+ }
+#else
+ err = xenbus_printf(dev->nodename, "shared-frame", "%lu",
+ virt_to_machine(blk_ring.sring) >> PAGE_SHIFT);
+ if (err) {
+ message = "writing shared-frame";
+ goto abort_transaction;
+ }
+#endif
+ err = xenbus_printf(dev->nodename,
+ "event-channel", "%u", blkif_evtchn);
+ if (err) {
+ message = "writing event-channel";
+ goto abort_transaction;
+ }
+
+ info->watch.node = info->backend = backend;
+ info->watch.callback = watch_for_status;
+
+ err = register_xenbus_watch(&info->watch);
+ if (err) {
+ message = "registering watch on backend";
+ goto abort_transaction;
+ }
+
+ err = xenbus_transaction_end(0);
+ if (err) {
+ xenbus_dev_error(dev, err, "completing transaction");
+ goto destroy_blkring;
+ }
+ return 0;
+
+abort_transaction:
+ xenbus_transaction_end(1);
+ /* Have to do this *outside* transaction. */
+ xenbus_dev_error(dev, err, "%s", message);
+destroy_blkring:
+ if (blkif_vbds == 0)
+ blkif_free();
+free_backend:
+ kfree(backend);
+out:
+ printk("%s:%u = %i\n", __FILE__, __LINE__, err);
+ return err;
+}
+
+/* Setup supplies the backend dir, virtual device.
+
+ We place an event channel and shared frame entries.
+ We watch backend to wait if it's ok. */
+static int blkfront_probe(struct xenbus_device *dev,
+ const struct xenbus_device_id *id)
+{
+ int err;
+ struct blkfront_info *info;
+ int vdevice;
+
+ /* FIXME: Use dynamic device id if this is not set. */
+ err = xenbus_scanf(dev->nodename, "virtual-device", "%i", &vdevice);
+ if (err == -ENOENT)
+ return err;
+ if (err < 0) {
+ xenbus_dev_error(dev, err, "reading virtual-device");
+ return err;
+ }
+
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
+ if (!info) {
+ xenbus_dev_error(dev, err, "allocating info structure");
+ return err;
+ }
+ info->dev = dev;
+ info->vdevice = vdevice;
+ info->connected = 0;
+ /* Front end dir is a number, which is used as the id. */
+ info->handle = simple_strtoul(strrchr(dev->nodename,'/')+1, NULL, 0);
+ dev->data = info;
+
+ err = talk_to_backend(dev, info);
+ if (err) {
+ kfree(info);
+ return err;
+ }
+
+ /* Call once in case entries already there. */
+ watch_for_status(&info->watch, info->watch.node);
+ blkif_vbds++;
+ return 0;
+}
+
+static int blkfront_remove(struct xenbus_device *dev)
+{
+ struct blkfront_info *info = dev->data;
+
+ if (info->backend)
+ unregister_xenbus_watch(&info->watch);
+
+ if (info->connected) {
+ xlvbd_del(info->handle);
+ blkif_vbds_connected--;
+ }
+ kfree(info->backend);
+ kfree(info);
+
+ if (--blkif_vbds == 0)
+ blkif_free();
+
+ return 0;
+}
+
+static int blkfront_suspend(struct xenbus_device *dev)
+{
+ struct blkfront_info *info = dev->data;
+
+ unregister_xenbus_watch(&info->watch);
+ kfree(info->backend);
+ info->backend = NULL;
+
+ if (--blkif_vbds == 0) {
+ recovery = 1;
+ blkif_free();
+ }
+
+ return 0;
+}
+
+static int blkfront_resume(struct xenbus_device *dev)
+{
+ struct blkfront_info *info = dev->data;
+ int err;
+
+ /* FIXME: Check geometry hasn't changed here... */
+ err = talk_to_backend(dev, info);
+ if (!err) {
+ if (blkif_vbds++ == 0)
+ blkif_recover();
+ }
+ return err;
+}
+
+static struct xenbus_driver blkfront = {
+ .name = "vbd",
+ .owner = THIS_MODULE,
+ .ids = blkfront_ids,
+ .probe = blkfront_probe,
+ .remove = blkfront_remove,
+ .resume = blkfront_resume,
+ .suspend = blkfront_suspend,
+};
+
+static void __init init_blk_xenbus(void)
+{
+ xenbus_register_device(&blkfront);
+}
+
+static int wait_for_blkif(void)
{
int err = 0;
int i;
- send_driver_status(1);
/*
* We should read 'nr_interfaces' from response message and wait
* for notifications before proceeding. For now we assume that we
* will be notified of exactly one interface.
*/
- for ( i=0; (blkif_state != BLKIF_STATE_CONNECTED) && (i < 10*HZ); i++ )
+ for ( i=0; blkif_state != BLKIF_STATE_CONNECTED && (i < 10*HZ); i++ )
{
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(1);
@@ -1419,7 +1421,7 @@
return err;
}
-int __init xlblk_init(void)
+static int __init xlblk_init(void)
{
int i;
@@ -1443,27 +1445,11 @@
blk_shadow[i].req.id = i+1;
blk_shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff;
- (void)ctrl_if_register_receiver(CMSG_BLKIF_FE, blkif_ctrlif_rx,
- CALLBACK_IN_BLOCKING_CONTEXT);
+ init_blk_xenbus();
wait_for_blkif();
return 0;
-}
-
-void blkdev_suspend(void)
-{
-}
-
-void blkdev_resume(void)
-{
-#ifdef CONFIG_XEN_BLKDEV_GRANT
- int i, j;
- for ( i = 0; i < BLK_RING_SIZE; i++ )
- for ( j = 0; j < BLKIF_MAX_SEGMENTS_PER_REQUEST; j++ )
- blk_shadow[i].req.frame_and_sects[j] |= GRANTREF_INVALID;
-#endif
- send_driver_status(1);
}
static void blkif_completion(struct blk_shadow *s)
diff -r 509316987d65 -r 66348ff38ec1
linux-2.6-xen-sparse/drivers/xen/blkfront/block.h
--- a/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h Fri Aug 19 10:50:15 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h Fri Aug 19 13:08:50 2005
@@ -100,6 +100,7 @@
struct xlbd_disk_info {
int xd_device;
+ blkif_vdev_t handle;
struct xlbd_major_info *mi;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
struct xlbd_disk_info *next_waiting;
@@ -119,17 +120,10 @@
unsigned command, unsigned long argument);
extern int blkif_check(dev_t dev);
extern int blkif_revalidate(dev_t dev);
-extern void blkif_control_send(blkif_request_t *req, blkif_response_t *rsp);
-#ifdef CONFIG_XEN_BLKDEV_GRANT
-extern void blkif_control_probe_send(
- blkif_request_t *req, blkif_response_t *rsp, unsigned long address);
-#endif
extern void do_blkif_request (request_queue_t *rq);
-extern void xlvbd_update_vbds(void);
-
/* Virtual block-device subsystem. */
-extern int xlvbd_init(void);
-extern void xlvbd_cleanup(void);
-
+int xlvbd_add(blkif_sector_t capacity, int device, blkif_vdev_t handle,
+ u16 info, u16 sector_size);
+void xlvbd_del(blkif_vdev_t handle);
#endif /* __XEN_DRIVERS_BLOCK_H__ */
diff -r 509316987d65 -r 66348ff38ec1
linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c Fri Aug 19 10:50:15 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c Fri Aug 19 13:08:50 2005
@@ -46,8 +46,9 @@
struct lvdisk
{
blkif_sector_t capacity; /* 0: Size in terms of 512-byte sectors. */
- blkif_vdev_t device; /* 8: Device number (opaque 16 bit value). */
- u16 info;
+ blkif_vdev_t handle; /* 8: Device number (opaque 16 bit value). */
+ u16 info;
+ dev_t dev;
struct list_head list;
};
@@ -85,7 +86,7 @@
/* Information about our VBDs. */
#define MAX_VBDS 64
-struct list_head vbds_list;
+static LIST_HEAD(vbds_list);
#define MAJOR_XEN(dev) ((dev)>>8)
#define MINOR_XEN(dev) ((dev) & 0xff)
@@ -116,49 +117,6 @@
{
list_del(&disk->list);
kfree(disk);
-}
-
-static vdisk_t *xlvbd_probe(int *ret)
-{
- blkif_response_t rsp;
- blkif_request_t req;
- vdisk_t *disk_info = NULL;
- unsigned long buf;
- int nr;
-
- buf = __get_free_page(GFP_KERNEL);
- if ((void *)buf == NULL)
- goto out;
-
- memset(&req, 0, sizeof(req));
- req.operation = BLKIF_OP_PROBE;
- req.nr_segments = 1;
-#ifdef CONFIG_XEN_BLKDEV_GRANT
- blkif_control_probe_send(&req, &rsp,
- (unsigned long)(virt_to_machine(buf)));
-#else
- req.frame_and_sects[0] = blkif_fas(virt_to_machine(buf), 0,
(PAGE_SIZE/512)-1);
-
- blkif_control_send(&req, &rsp);
-#endif
- if ( rsp.status <= 0 ) {
- WPRINTK("Could not probe disks (%d)\n", rsp.status);
- goto out;
- }
- nr = rsp.status;
- if ( nr > MAX_VBDS )
- nr = MAX_VBDS;
-
- disk_info = kmalloc(nr * sizeof(vdisk_t), GFP_KERNEL);
- if (disk_info != NULL)
- memcpy(disk_info, (void *) buf, nr * sizeof(vdisk_t));
-
- if (ret != NULL)
- *ret = nr;
-
-out:
- free_page(buf);
- return disk_info;
}
static struct xlbd_major_info *xlbd_alloc_major_info(
@@ -189,6 +147,7 @@
break;
}
+ printk("Registering block device major %i\n", ptr->major);
if (register_blkdev(ptr->major, ptr->type->devname)) {
WPRINTK("can't get major %d with name %s\n",
ptr->major, ptr->type->devname);
@@ -231,7 +190,7 @@
xlbd_alloc_major_info(major, minor, index));
}
-static int xlvbd_init_blk_queue(struct gendisk *gd, vdisk_t *disk)
+static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size)
{
request_queue_t *rq;
@@ -242,7 +201,7 @@
elevator_init(rq, "noop");
/* Hard sector size and max sectors impersonate the equiv. hardware. */
- blk_queue_hardsect_size(rq, disk->sector_size);
+ blk_queue_hardsect_size(rq, sector_size);
blk_queue_max_sectors(rq, 512);
/* Each segment in a request is up to an aligned page in size. */
@@ -261,8 +220,9 @@
return 0;
}
-struct gendisk *xlvbd_alloc_gendisk(
- struct xlbd_major_info *mi, int minor, vdisk_t *disk)
+static struct gendisk *xlvbd_alloc_gendisk(
+ struct xlbd_major_info *mi, int minor, blkif_sector_t capacity,
+ int device, blkif_vdev_t handle, u16 info, u16 sector_size)
{
struct gendisk *gd;
struct xlbd_disk_info *di;
@@ -273,7 +233,8 @@
return NULL;
memset(di, 0, sizeof(*di));
di->mi = mi;
- di->xd_device = disk->device;
+ di->xd_device = device;
+ di->handle = handle;
if ((minor & ((1 << mi->type->partn_shift) - 1)) == 0)
nr_minors = 1 << mi->type->partn_shift;
@@ -296,22 +257,22 @@
gd->first_minor = minor;
gd->fops = &xlvbd_block_fops;
gd->private_data = di;
- set_capacity(gd, disk->capacity);
-
- if (xlvbd_init_blk_queue(gd, disk)) {
+ set_capacity(gd, capacity);
+
+ if (xlvbd_init_blk_queue(gd, sector_size)) {
del_gendisk(gd);
goto out;
}
di->rq = gd->queue;
- if (disk->info & VDISK_READONLY)
+ if (info & VDISK_READONLY)
set_disk_ro(gd, 1);
- if (disk->info & VDISK_REMOVABLE)
+ if (info & VDISK_REMOVABLE)
gd->flags |= GENHD_FL_REMOVABLE;
- if (disk->info & VDISK_CDROM)
+ if (info & VDISK_CDROM)
gd->flags |= GENHD_FL_CD;
add_disk(gd);
@@ -323,38 +284,36 @@
return NULL;
}
-static int xlvbd_device_add(struct list_head *list, vdisk_t *disk)
+int xlvbd_add(blkif_sector_t capacity, int device, blkif_vdev_t handle,
+ u16 info, u16 sector_size)
{
struct lvdisk *new;
- int minor;
- dev_t device;
struct block_device *bd;
struct gendisk *gd;
struct xlbd_major_info *mi;
- mi = xlbd_get_major_info(disk->device);
+ mi = xlbd_get_major_info(device);
if (mi == NULL)
return -EPERM;
new = xlvbd_device_alloc();
if (new == NULL)
- return -1;
- new->capacity = disk->capacity;
- new->device = disk->device;
- new->info = disk->info;
-
- minor = MINOR_XEN(disk->device);
- device = MKDEV(mi->major, minor);
-
- bd = bdget(device);
+ return -ENOMEM;
+ new->capacity = capacity;
+ new->info = info;
+ new->handle = handle;
+ new->dev = MKDEV(MAJOR_XEN(device), MINOR_XEN(device));
+
+ bd = bdget(new->dev);
if (bd == NULL)
goto out;
- gd = xlvbd_alloc_gendisk(mi, minor, disk);
+ gd = xlvbd_alloc_gendisk(mi, MINOR_XEN(device), capacity, device, handle,
+ info, sector_size);
if (gd == NULL)
goto out_bd;
- list_add(&new->list, list);
+ list_add(&new->list, &vbds_list);
out_bd:
bdput(bd);
out:
@@ -363,27 +322,26 @@
static int xlvbd_device_del(struct lvdisk *disk)
{
- dev_t device;
struct block_device *bd;
struct gendisk *gd;
struct xlbd_disk_info *di;
int ret = 0, unused;
request_queue_t *rq;
- device = MKDEV(MAJOR_XEN(disk->device), MINOR_XEN(disk->device));
-
- bd = bdget(device);
+ bd = bdget(disk->dev);
if (bd == NULL)
return -1;
- gd = get_gendisk(device, &unused);
+ gd = get_gendisk(disk->dev, &unused);
di = gd->private_data;
+#if 0 /* This is wrong: hda and hdb share same major, for example. */
if (di->mi->usage != 0) {
- WPRINTK("disk removal failed: used [dev=%x]\n", device);
+ WPRINTK("disk removal failed: used [dev=%x]\n", disk->dev);
ret = -1;
goto out;
}
+#endif
rq = gd->queue;
del_gendisk(gd);
@@ -391,110 +349,19 @@
blk_cleanup_queue(rq);
xlvbd_device_free(disk);
-out:
bdput(bd);
return ret;
}
-static int xlvbd_device_update(struct lvdisk *ldisk, vdisk_t *disk)
-{
- dev_t device;
- struct block_device *bd;
- struct gendisk *gd;
- int unused;
-
- if ((ldisk->capacity == disk->capacity) && (ldisk->info == disk->info))
- return 0;
-
- device = MKDEV(MAJOR_XEN(ldisk->device), MINOR_XEN(ldisk->device));
-
- bd = bdget(device);
- if (bd == NULL)
- return -1;
-
- gd = get_gendisk(device, &unused);
- set_capacity(gd, disk->capacity);
- ldisk->capacity = disk->capacity;
-
- bdput(bd);
-
- return 0;
-}
-
-void xlvbd_refresh(void)
-{
- vdisk_t *newdisks;
- struct list_head *tmp, *tmp2;
- struct lvdisk *disk;
- int i, nr;
-
- newdisks = xlvbd_probe(&nr);
- if (newdisks == NULL) {
- WPRINTK("failed to probe\n");
- return;
- }
-
- i = 0;
- list_for_each_safe(tmp, tmp2, &vbds_list) {
- disk = list_entry(tmp, struct lvdisk, list);
-
- for (i = 0; i < nr; i++) {
- if ( !newdisks[i].device )
- continue;
- if ( disk->device == newdisks[i].device ) {
- xlvbd_device_update(disk, &newdisks[i]);
- newdisks[i].device = 0;
- break;
- }
- }
- if (i == nr) {
- xlvbd_device_del(disk);
- newdisks[i].device = 0;
- }
- }
- for (i = 0; i < nr; i++)
- if ( newdisks[i].device )
- xlvbd_device_add(&vbds_list, &newdisks[i]);
- kfree(newdisks);
-}
-
-/*
- * xlvbd_update_vbds - reprobes the VBD status and performs updates driver
- * state. The VBDs need to be updated in this way when the domain is
- * initialised and also each time we receive an XLBLK_UPDATE event.
- */
-void xlvbd_update_vbds(void)
-{
- xlvbd_refresh();
-}
-
-/*
- * Set up all the linux device goop for the virtual block devices
- * (vbd's) that we know about. Note that although from the backend
- * driver's p.o.v. VBDs are addressed simply an opaque 16-bit device
- * number, the domain creation tools conventionally allocate these
- * numbers to correspond to those used by 'real' linux -- this is just
- * for convenience as it means e.g. that the same /etc/fstab can be
- * used when booting with or without Xen.
- */
-int xlvbd_init(void)
-{
- int i, nr;
- vdisk_t *disks;
-
- INIT_LIST_HEAD(&vbds_list);
-
- memset(major_info, 0, sizeof(major_info));
-
- disks = xlvbd_probe(&nr);
- if (disks == NULL) {
- WPRINTK("failed to probe\n");
- return -1;
- }
-
- for (i = 0; i < nr; i++)
- xlvbd_device_add(&vbds_list, &disks[i]);
-
- kfree(disks);
- return 0;
-}
+void xlvbd_del(blkif_vdev_t handle)
+{
+ struct lvdisk *i;
+
+ list_for_each_entry(i, &vbds_list, list) {
+ if (i->handle == handle) {
+ xlvbd_device_del(i);
+ return;
+ }
+ }
+ BUG();
+}
diff -r 509316987d65 -r 66348ff38ec1
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Fri Aug 19
10:50:15 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Fri Aug 19
13:08:50 2005
@@ -168,6 +168,8 @@
struct xenbus_driver *drv = to_xenbus_driver(_dev->driver);
const struct xenbus_device_id *id;
+ BUG_ON(!dev->driver);
+
if (!drv->probe)
return -ENODEV;
@@ -531,10 +533,13 @@
static int suspend_dev(struct device *dev, void *data)
{
int err = 0;
- struct xenbus_driver *drv = to_xenbus_driver(dev->driver);
- struct xenbus_device *xdev
- = container_of(dev, struct xenbus_device, dev);
-
+ struct xenbus_driver *drv;
+ struct xenbus_device *xdev;
+
+ if (dev->driver == NULL)
+ return 0;
+ drv = to_xenbus_driver(dev->driver);
+ xdev = container_of(dev, struct xenbus_device, dev);
if (drv->suspend)
err = drv->suspend(xdev);
if (err)
@@ -545,10 +550,13 @@
static int resume_dev(struct device *dev, void *data)
{
int err = 0;
- struct xenbus_driver *drv = to_xenbus_driver(dev->driver);
- struct xenbus_device *xdev
- = container_of(dev, struct xenbus_device, dev);
-
+ struct xenbus_driver *drv;
+ struct xenbus_device *xdev;
+
+ if (dev->driver == NULL)
+ return 0;
+ drv = to_xenbus_driver(dev->driver);
+ xdev = container_of(dev, struct xenbus_device, dev);
if (drv->resume)
err = drv->resume(xdev);
if (err)
diff -r 509316987d65 -r 66348ff38ec1 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py Fri Aug 19 10:50:15 2005
+++ b/tools/python/xen/xend/XendDomainInfo.py Fri Aug 19 13:08:50 2005
@@ -36,8 +36,10 @@
from xen.xend.server import SrvDaemon; xend = SrvDaemon.instance()
from xen.xend.server import messages
from xen.xend.server.channel import EventChannel, channelFactory
+from xen.util.blkif import blkdev_name_to_number, expand_dev_name
from xen.xend import sxp
+from xen.xend import Blkctl
from xen.xend.PrettyPrint import prettyprintstring
from xen.xend.XendBootloader import bootloader
from xen.xend.XendLogging import log
@@ -380,6 +382,39 @@
return ctrl
def createDevice(self, type, devconfig, change=False):
+ if type == 'vbd':
+
+ backdom = domain_exists(sxp.child_value(devconfig, 'backend', '0'))
+
+ devnum = blkdev_name_to_number(sxp.child_value(devconfig, 'dev'))
+
+ # create backend db
+ backdb = backdom.db.addChild("/backend/%s/%s/%d" %
+ (type, self.uuid, devnum))
+
+ # create frontend db
+ db = self.db.addChild("/device/%s/%d" % (type, devnum))
+
+ db['virtual-device'] = "%i" % devnum
+ #db['backend'] = sxp.child_value(devconfig, 'backend', '0')
+ db['backend'] = backdb.getPath()
+ db['backend-id'] = "%i" % int(sxp.child_value(devconfig,
+ 'backend', '0'))
+
+ backdb['frontend'] = db.getPath()
+ (type, params) = string.split(sxp.child_value(devconfig, 'uname'),
':', 1)
+ node = Blkctl.block('bind', type, params)
+ backdb['frontend-id'] = "%i" % self.id
+ backdb['physical-device'] = "%li" % blkdev_name_to_number(node)
+ backdb.saveDB(save=True)
+
+ # Ok, super gross, this really doesn't belong in the frontend db...
+ db['type'] = type
+ db['node'] = node
+ db['params'] = params
+ db.saveDB(save=True)
+
+ return
ctrl = self.findDeviceController(type)
return ctrl.createDevice(devconfig, recreate=self.recreate,
change=change)
@@ -671,6 +706,16 @@
for ctrl in self.getDeviceControllers():
if ctrl.isDestroyed(): continue
ctrl.destroyController(reboot=reboot)
+ ddb = self.db.addChild("/device")
+ for type in ddb.keys():
+ if type == 'vbd':
+ typedb = ddb.addChild(type)
+ for dev in typedb.keys():
+ devdb = typedb.addChild(str(dev))
+ Blkctl.block('unbind', devdb['type'].getData(),
+ devdb['node'].getData())
+ typedb[dev].delete()
+ typedb.saveDB(save=True)
def show(self):
"""Print virtual machine info.
@@ -926,6 +971,7 @@
at creation time, for example when it uses NFS root.
"""
+ return
blkif = self.getDeviceController("vbd", error=False)
if not blkif:
blkif = self.createDeviceController("vbd")
diff -r 509316987d65 -r 66348ff38ec1 xen/include/public/io/blkif.h
--- a/xen/include/public/io/blkif.h Fri Aug 19 10:50:15 2005
+++ b/xen/include/public/io/blkif.h Fri Aug 19 13:08:50 2005
@@ -18,7 +18,6 @@
#define BLKIF_OP_READ 0
#define BLKIF_OP_WRITE 1
-#define BLKIF_OP_PROBE 2
/* NB. Ring size must be small enough for sizeof(blkif_ring_t) <= PAGE_SIZE. */
#define BLKIF_RING_SIZE 64
@@ -33,7 +32,7 @@
typedef struct blkif_request {
u8 operation; /* BLKIF_OP_??? */
u8 nr_segments; /* number of segments */
- blkif_vdev_t device; /* only for read/write requests */
+ blkif_vdev_t handle; /* only for read/write requests */
unsigned long id; /* private guest value, echoed in resp */
blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */
/* @f_a_s[4:0]=last_sect ; @f_a_s[9:5]=first_sect */
@@ -71,31 +70,8 @@
DEFINE_RING_TYPES(blkif, blkif_request_t, blkif_response_t);
-/*
- * BLKIF_OP_PROBE:
- * The request format for a probe request is constrained as follows:
- * @operation == BLKIF_OP_PROBE
- * @nr_segments == size of probe buffer in pages
- * @device == unused (zero)
- * @id == any value (echoed in response message)
- * @sector_num == unused (zero)
- * @frame_and_sects == list of page-sized buffers.
- * (i.e., @first_sect == 0, @last_sect == 7).
- *
- * The response is a list of vdisk_t elements copied into the out-of-band
- * probe buffer. On success the response status field contains the number
- * of vdisk_t elements.
- */
-
#define VDISK_CDROM 0x1
#define VDISK_REMOVABLE 0x2
#define VDISK_READONLY 0x4
-typedef struct vdisk {
- blkif_sector_t capacity; /* Size in terms of 512-byte sectors. */
- blkif_vdev_t device; /* Device number (opaque 16 bit value). */
- u16 info; /* Device type and flags (VDISK_*). */
- u16 sector_size; /* Minimum alignment for requests. */
-} vdisk_t; /* 16 bytes */
-
#endif /* __XEN_PUBLIC_IO_BLKIF_H__ */
diff -r 509316987d65 -r 66348ff38ec1
linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c
--- /dev/null Fri Aug 19 10:50:15 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Fri Aug 19 13:08:50 2005
@@ -0,0 +1,308 @@
+/* Xenbus code for blkif backend
+ Copyright (C) 2005 Rusty Russell <rusty@xxxxxxxxxxxxxxx>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+#include <stdarg.h>
+#include <linux/module.h>
+#include <asm-xen/xenbus.h>
+#include "common.h"
+
+struct backend_info
+{
+ struct xenbus_device *dev;
+
+ /* our communications channel */
+ blkif_t *blkif;
+ struct vbd *vbd;
+
+ long int frontend_id;
+ long int pdev;
+ long int readonly;
+
+ /* watch back end for changes */
+ struct xenbus_watch backend_watch;
+
+ /* watch front end for changes */
+ struct xenbus_watch watch;
+ char *frontpath;
+};
+
+static int blkback_remove(struct xenbus_device *dev)
+{
+ struct backend_info *be = dev->data;
+
+ if (be->watch.node)
+ unregister_xenbus_watch(&be->watch);
+ unregister_xenbus_watch(&be->backend_watch);
+ if (be->vbd)
+ vbd_free(be->blkif, be->vbd);
+ if (be->blkif)
+ blkif_put(be->blkif);
+ if (be->frontpath)
+ kfree(be->frontpath);
+ kfree(be);
+ return 0;
+}
+
+/* Front end tells us frame. */
+static void frontend_changed(struct xenbus_watch *watch, const char *node)
+{
+ unsigned long sharedmfn;
+ unsigned int evtchn;
+ int err;
+ struct backend_info *be
+ = container_of(watch, struct backend_info, watch);
+
+ /* If other end is gone, delete ourself. */
+ if (!xenbus_exists(be->frontpath, "")) {
+ xenbus_rm(be->dev->nodename, "");
+ device_unregister(&be->dev->dev);
+ return;
+ }
+ if (vbd_is_active(be->vbd))
+ return;
+
+#ifndef CONFIG_XEN_BLKDEV_GRANT
+ err = xenbus_gather(be->frontpath, "shared-frame", "%lu", &sharedmfn,
+ "event-channel", "%u", &evtchn, NULL);
+ if (err) {
+ xenbus_dev_error(be->dev, err,
+ "reading %s/shared-frame and event-channel",
+ be->frontpath);
+ return;
+ }
+#else
+ err = xenbus_gather(be->frontpath, "grant-id", "%lu", &sharedmfn,
+ "event-channel", "%u", &evtchn, NULL);
+ if (err) {
+ xenbus_dev_error(be->dev, err,
+ "reading %s/grant-id and event-channel",
+ be->frontpath);
+ return;
+ }
+#endif
+
+ /* Domains must use same shared frame for all vbds. */
+ if (be->blkif->status == CONNECTED &&
+ (evtchn != be->blkif->remote_evtchn ||
+ sharedmfn != be->blkif->shmem_frame)) {
+ xenbus_dev_error(be->dev, err,
+ "Shared frame/evtchn %li/%u not same as"
+ " old %li/%u",
+ sharedmfn, evtchn,
+ be->blkif->shmem_frame,
+ be->blkif->remote_evtchn);
+ return;
+ }
+
+ /* Supply the information about the device the frontend needs */
+ err = xenbus_transaction_start(be->dev->nodename);
+ if (err) {
+ xenbus_dev_error(be->dev, err, "starting transaction");
+ return;
+ }
+
+ err = xenbus_printf(be->dev->nodename, "sectors", "%lu",
+ vbd_size(be->vbd));
+ if (err) {
+ xenbus_dev_error(be->dev, err, "writing %s/sectors",
+ be->dev->nodename);
+ goto abort;
+ }
+
+ /* FIXME: use a typename instead */
+ err = xenbus_printf(be->dev->nodename, "info", "%u",
+ vbd_info(be->vbd));
+ if (err) {
+ xenbus_dev_error(be->dev, err, "writing %s/info",
+ be->dev->nodename);
+ goto abort;
+ }
+ err = xenbus_printf(be->dev->nodename, "sector-size", "%lu",
+ vbd_secsize(be->vbd));
+ if (err) {
+ xenbus_dev_error(be->dev, err, "writing %s/sector-size",
+ be->dev->nodename);
+ goto abort;
+ }
+
+ /* First vbd? We need to map the shared frame, irq etc. */
+ if (be->blkif->status != CONNECTED) {
+ err = blkif_map(be->blkif, sharedmfn, evtchn);
+ if (err) {
+ xenbus_dev_error(be->dev, err,
+ "mapping shared-frame %lu port %u",
+ sharedmfn, evtchn);
+ goto abort;
+ }
+ }
+
+ /* We're ready, activate. */
+ vbd_activate(be->blkif, be->vbd);
+
+ xenbus_transaction_end(0);
+ xenbus_dev_ok(be->dev);
+
+ return;
+
+abort:
+ xenbus_transaction_end(1);
+}
+
+/*
+ Setup supplies physical device.
+ We provide event channel and device details to front end.
+ Frontend supplies shared frame and event channel.
+ */
+static void backend_changed(struct xenbus_watch *watch, const char *node)
+{
+ int err;
+ char *p;
+ char *frontend;
+ long int handle, pdev;
+ struct backend_info *be
+ = container_of(watch, struct backend_info, backend_watch);
+ struct xenbus_device *dev = be->dev;
+
+ frontend = NULL;
+ err = xenbus_gather(dev->nodename,
+ "frontend-id", "%li", &be->frontend_id,
+ "frontend", NULL, &frontend,
+ NULL);
+ if (err == -ENOENT || err == -ERANGE ||
+ strlen(frontend) == 0 || !xenbus_exists(frontend, "")) {
+ if (frontend)
+ kfree(frontend);
+ /* If we can't get a frontend path and a frontend-id,
+ * then our bus-id is no longer valid and we need to
+ * destroy the backend device.
+ */
+ goto device_fail;
+ }
+
+ if (!be->frontpath || strcmp(frontend, be->frontpath)) {
+ if (be->watch.node)
+ unregister_xenbus_watch(&be->watch);
+ if (be->frontpath)
+ kfree(be->frontpath);
+ be->frontpath = frontend;
+ be->watch.node = be->frontpath;
+ be->watch.callback = frontend_changed;
+ err = register_xenbus_watch(&be->watch);
+ if (err) {
+ be->watch.node = NULL;
+ goto device_fail;
+ }
+ } else
+ kfree(frontend);
+
+ err = xenbus_scanf(dev->nodename, "physical-device", "%li", &pdev);
+ if (err == -ENOENT || err == -ERANGE)
+ goto out;
+ if (err < 0) {
+ xenbus_dev_error(dev, err, "Reading physical-device");
+ goto device_fail;
+ }
+ if (be->pdev && be->pdev != pdev) {
+ printk(KERN_WARNING
+ "changing physical-device not supported\n");
+ goto device_fail;
+ }
+ be->pdev = pdev;
+
+ /* If there's a read-only node, we're read only. */
+ p = xenbus_read(dev->nodename, "read-only", NULL);
+ if (!IS_ERR(p)) {
+ be->readonly = 1;
+ kfree(p);
+ }
+
+ if (be->blkif == NULL) {
+ /* Front end dir is a number, which is used as the handle. */
+ p = strrchr(be->frontpath, '/') + 1;
+ handle = simple_strtoul(p, NULL, 0);
+
+ be->blkif = blkif_find(be->frontend_id);
+ if (IS_ERR(be->blkif)) {
+ err = PTR_ERR(be->blkif);
+ be->blkif = NULL;
+ goto device_fail;
+ }
+
+ be->vbd = vbd_create(be->blkif, handle, be->pdev,
+ be->readonly);
+ if (IS_ERR(be->vbd)) {
+ err = PTR_ERR(be->vbd);
+ be->vbd = NULL;
+ goto device_fail;
+ }
+
+ frontend_changed(&be->watch, be->frontpath);
+ }
+
+ return;
+
+ device_fail:
+ device_unregister(&be->dev->dev);
+ out:
+ return;
+}
+
+static int blkback_probe(struct xenbus_device *dev,
+ const struct xenbus_device_id *id)
+{
+ struct backend_info *be;
+ int err;
+
+ be = kmalloc(sizeof(*be), GFP_KERNEL);
+ if (!be)
+ return -ENOMEM;
+
+ memset(be, 0, sizeof(*be));
+
+ be->dev = dev;
+ be->backend_watch.node = dev->nodename;
+ be->backend_watch.callback = backend_changed;
+ err = register_xenbus_watch(&be->backend_watch);
+ if (err)
+ goto free_be;
+
+ dev->data = be;
+
+ backend_changed(&be->backend_watch, dev->nodename);
+ return err;
+ free_be:
+ kfree(be);
+ return err;
+}
+
+static struct xenbus_device_id blkback_ids[] = {
+ { "vbd" },
+ { "" }
+};
+
+static struct xenbus_driver blkback = {
+ .name = "vbd",
+ .owner = THIS_MODULE,
+ .ids = blkback_ids,
+ .probe = blkback_probe,
+ .remove = blkback_remove,
+};
+
+void blkif_xenbus_init(void)
+{
+ xenbus_register_backend(&blkback);
+}
diff -r 509316987d65 -r 66348ff38ec1
linux-2.6-xen-sparse/drivers/xen/blkback/control.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkback/control.c Fri Aug 19
10:50:15 2005
+++ /dev/null Fri Aug 19 13:08:50 2005
@@ -1,61 +0,0 @@
-/******************************************************************************
- * arch/xen/drivers/blkif/backend/control.c
- *
- * Routines for interfacing with the control plane.
- *
- * Copyright (c) 2004, Keir Fraser
- */
-
-#include "common.h"
-
-static void blkif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
-{
- DPRINTK("Received blkif backend message, subtype=%d\n", msg->subtype);
-
- switch ( msg->subtype )
- {
- case CMSG_BLKIF_BE_CREATE:
- blkif_create((blkif_be_create_t *)&msg->msg[0]);
- break;
- case CMSG_BLKIF_BE_DESTROY:
- blkif_destroy((blkif_be_destroy_t *)&msg->msg[0]);
- break;
- case CMSG_BLKIF_BE_CONNECT:
- blkif_connect((blkif_be_connect_t *)&msg->msg[0]);
- break;
- case CMSG_BLKIF_BE_DISCONNECT:
- if ( !blkif_disconnect((blkif_be_disconnect_t *)&msg->msg[0],msg->id) )
- return; /* Sending the response is deferred until later. */
- break;
- case CMSG_BLKIF_BE_VBD_CREATE:
- vbd_create((blkif_be_vbd_create_t *)&msg->msg[0]);
- break;
- case CMSG_BLKIF_BE_VBD_DESTROY:
- vbd_destroy((blkif_be_vbd_destroy_t *)&msg->msg[0]);
- break;
- default:
- DPRINTK("Parse error while reading message subtype %d, len %d\n",
- msg->subtype, msg->length);
- msg->length = 0;
- break;
- }
-
- ctrl_if_send_response(msg);
-}
-
-void blkif_ctrlif_init(void)
-{
- ctrl_msg_t cmsg;
- blkif_be_driver_status_t st;
-
- (void)ctrl_if_register_receiver(CMSG_BLKIF_BE, blkif_ctrlif_rx,
- CALLBACK_IN_BLOCKING_CONTEXT);
-
- /* Send a driver-UP notification to the domain controller. */
- cmsg.type = CMSG_BLKIF_BE;
- cmsg.subtype = CMSG_BLKIF_BE_DRIVER_STATUS;
- cmsg.length = sizeof(blkif_be_driver_status_t);
- st.status = BLKIF_DRIVER_STATUS_UP;
- memcpy(cmsg.msg, &st, sizeof(st));
- ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
-}
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|