debuggers.hg

view linux-2.6-xen-sparse/drivers/xen/blktap/interface.c @ 6649:f59e0163540e

Updates to blktap driver and user code.

Mostly this makes the tap code work again with all of the changes that
have happened to the block drivers recently. We now use a shared page
per VBD (to the driver), and handle control information through the
store. The taplib interfaces have changed to be based around per-vbd
data structures that you can attach arbitrary handlers for.

There is also initial code for a user-level blockback driver, which
aims to get around the use of loopbacks for file-based vbds. Still
plenty of work to do here -- this is a working incremental checkin and
I'm away from this for the next four weeks.

Signed-off-by: Andrew Warfield <andrew.warfield@cl.cam.ac.uk>
author akw27@arcadians.cl.cam.ac.uk
date Sun Sep 04 21:19:44 2005 +0000 (2005-09-04)
parents
children b2f4823b6ff0 b35215021b32 9af349b055e5 3233e7ecfa9f
line source
1 /******************************************************************************
2 * arch/xen/drivers/blkif/backend/interface.c
3 *
4 * Block-device interface management.
5 *
6 * Copyright (c) 2004, Keir Fraser
7 */
9 #include "common.h"
10 #include <asm-xen/evtchn.h>
12 static kmem_cache_t *blkif_cachep;
14 blkif_t *alloc_blkif(domid_t domid)
15 {
16 blkif_t *blkif;
18 blkif = kmem_cache_alloc(blkif_cachep, GFP_KERNEL);
19 if (!blkif)
20 return ERR_PTR(-ENOMEM);
22 memset(blkif, 0, sizeof(*blkif));
23 blkif->domid = domid;
24 blkif->status = DISCONNECTED;
25 spin_lock_init(&blkif->blk_ring_lock);
26 atomic_set(&blkif->refcnt, 1);
28 return blkif;
29 }
31 static int map_frontend_page(blkif_t *blkif, unsigned long localaddr,
32 unsigned long shared_page)
33 {
34 struct gnttab_map_grant_ref op;
35 op.host_addr = localaddr;
36 op.flags = GNTMAP_host_map;
37 op.ref = shared_page;
38 op.dom = blkif->domid;
40 BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) );
42 if (op.handle < 0) {
43 DPRINTK(" Grant table operation failure !\n");
44 return op.handle;
45 }
47 blkif->shmem_ref = shared_page;
48 blkif->shmem_handle = op.handle;
49 blkif->shmem_vaddr = localaddr;
50 return 0;
51 }
53 static void unmap_frontend_page(blkif_t *blkif)
54 {
55 struct gnttab_unmap_grant_ref op;
57 op.host_addr = blkif->shmem_vaddr;
58 op.handle = blkif->shmem_handle;
59 op.dev_bus_addr = 0;
60 BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
61 }
63 int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn)
64 {
65 struct vm_struct *vma;
66 blkif_sring_t *sring;
67 evtchn_op_t op = { .cmd = EVTCHNOP_bind_interdomain };
68 int err;
70 BUG_ON(blkif->remote_evtchn);
72 if ( (vma = get_vm_area(PAGE_SIZE, VM_IOREMAP)) == NULL )
73 return -ENOMEM;
75 err = map_frontend_page(blkif, (unsigned long)vma->addr, shared_page);
76 if (err) {
77 vfree(vma->addr);
78 return err;
79 }
81 op.u.bind_interdomain.dom1 = DOMID_SELF;
82 op.u.bind_interdomain.dom2 = blkif->domid;
83 op.u.bind_interdomain.port1 = 0;
84 op.u.bind_interdomain.port2 = evtchn;
85 err = HYPERVISOR_event_channel_op(&op);
86 if (err) {
87 unmap_frontend_page(blkif);
88 vfree(vma->addr);
89 return err;
90 }
92 blkif->evtchn = op.u.bind_interdomain.port1;
93 blkif->remote_evtchn = evtchn;
95 sring = (blkif_sring_t *)vma->addr;
96 SHARED_RING_INIT(sring);
97 BACK_RING_INIT(&blkif->blk_ring, sring, PAGE_SIZE);
99 bind_evtchn_to_irqhandler(blkif->evtchn, blkif_be_int, 0, "blkif-backend",
100 blkif);
101 blkif->status = CONNECTED;
102 blkif->shmem_frame = shared_page;
104 return 0;
105 }
107 static void free_blkif(void *arg)
108 {
109 evtchn_op_t op = { .cmd = EVTCHNOP_close };
110 blkif_t *blkif = (blkif_t *)arg;
112 op.u.close.port = blkif->evtchn;
113 op.u.close.dom = DOMID_SELF;
114 HYPERVISOR_event_channel_op(&op);
115 op.u.close.port = blkif->remote_evtchn;
116 op.u.close.dom = blkif->domid;
117 HYPERVISOR_event_channel_op(&op);
119 if (blkif->evtchn)
120 unbind_evtchn_from_irqhandler(blkif->evtchn, blkif);
122 if (blkif->blk_ring.sring) {
123 unmap_frontend_page(blkif);
124 vfree(blkif->blk_ring.sring);
125 blkif->blk_ring.sring = NULL;
126 }
128 kmem_cache_free(blkif_cachep, blkif);
129 }
131 void free_blkif_callback(blkif_t *blkif)
132 {
133 INIT_WORK(&blkif->free_work, free_blkif, (void *)blkif);
134 schedule_work(&blkif->free_work);
135 }
137 void __init blkif_interface_init(void)
138 {
139 blkif_cachep = kmem_cache_create("blkif_cache", sizeof(blkif_t),
140 0, 0, NULL, NULL);
141 }