Tue Jun 7 16:41:14 2011 UTC ()
Be more consistent for event handler naming with block backend: it is
xbdback(4) rather than xbd(4), and use i for identifier separation
(like xvif(4)).

The name is not used outside from event counters (vmstat -i), so
should be transparent to Xen block scripts.


(jym)
diff -r1.38 -r1.39 src/sys/arch/xen/xen/xbdback_xenbus.c

cvs diff -r1.38 -r1.39 src/sys/arch/xen/xen/xbdback_xenbus.c (switch to unified diff)

--- src/sys/arch/xen/xen/xbdback_xenbus.c 2011/05/26 22:16:42 1.38
+++ src/sys/arch/xen/xen/xbdback_xenbus.c 2011/06/07 16:41:14 1.39
@@ -1,1596 +1,1596 @@ @@ -1,1596 +1,1596 @@
1/* $NetBSD: xbdback_xenbus.c,v 1.38 2011/05/26 22:16:42 jym Exp $ */ 1/* $NetBSD: xbdback_xenbus.c,v 1.39 2011/06/07 16:41:14 jym Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2006 Manuel Bouyer. 4 * Copyright (c) 2006 Manuel Bouyer.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
14 * 14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 * 25 *
26 */ 26 */
27 27
28#include <sys/cdefs.h> 28#include <sys/cdefs.h>
29__KERNEL_RCSID(0, "$NetBSD: xbdback_xenbus.c,v 1.38 2011/05/26 22:16:42 jym Exp $"); 29__KERNEL_RCSID(0, "$NetBSD: xbdback_xenbus.c,v 1.39 2011/06/07 16:41:14 jym Exp $");
30 30
31#include <sys/types.h> 31#include <sys/types.h>
32#include <sys/param.h> 32#include <sys/param.h>
33#include <sys/systm.h> 33#include <sys/systm.h>
34#include <sys/malloc.h> 34#include <sys/malloc.h>
35#include <sys/queue.h> 35#include <sys/queue.h>
36#include <sys/kernel.h> 36#include <sys/kernel.h>
37#include <sys/atomic.h> 37#include <sys/atomic.h>
38#include <sys/conf.h> 38#include <sys/conf.h>
39#include <sys/disk.h> 39#include <sys/disk.h>
40#include <sys/disklabel.h> 40#include <sys/disklabel.h>
41#include <sys/fcntl.h> 41#include <sys/fcntl.h>
42#include <sys/vnode.h> 42#include <sys/vnode.h>
43#include <sys/kauth.h> 43#include <sys/kauth.h>
44#include <sys/workqueue.h> 44#include <sys/workqueue.h>
45#include <sys/buf.h> 45#include <sys/buf.h>
46 46
47#include <xen/xen.h> 47#include <xen/xen.h>
48#include <xen/xen_shm.h> 48#include <xen/xen_shm.h>
49#include <xen/evtchn.h> 49#include <xen/evtchn.h>
50#include <xen/xenbus.h> 50#include <xen/xenbus.h>
51#include <xen/xen3-public/io/protocols.h> 51#include <xen/xen3-public/io/protocols.h>
52 52
53/* #define XENDEBUG_VBD */ 53/* #define XENDEBUG_VBD */
54#ifdef XENDEBUG_VBD 54#ifdef XENDEBUG_VBD
55#define XENPRINTF(x) printf x 55#define XENPRINTF(x) printf x
56#else 56#else
57#define XENPRINTF(x) 57#define XENPRINTF(x)
58#endif 58#endif
59 59
60#define BLKIF_RING_SIZE __RING_SIZE((blkif_sring_t *)0, PAGE_SIZE) 60#define BLKIF_RING_SIZE __RING_SIZE((blkif_sring_t *)0, PAGE_SIZE)
61 61
62/* 62/*
63 * Backend block device driver for Xen 63 * Backend block device driver for Xen
64 */ 64 */
65 65
66/* Max number of pages per request. The request may not be page aligned */ 66/* Max number of pages per request. The request may not be page aligned */
67#define BLKIF_MAX_PAGES_PER_REQUEST (BLKIF_MAX_SEGMENTS_PER_REQUEST + 1) 67#define BLKIF_MAX_PAGES_PER_REQUEST (BLKIF_MAX_SEGMENTS_PER_REQUEST + 1)
68 68
69/* Values are expressed in 512-byte sectors */ 69/* Values are expressed in 512-byte sectors */
70#define VBD_BSIZE 512 70#define VBD_BSIZE 512
71#define VBD_MAXSECT ((PAGE_SIZE / VBD_BSIZE) - 1) 71#define VBD_MAXSECT ((PAGE_SIZE / VBD_BSIZE) - 1)
72 72
73struct xbdback_request; 73struct xbdback_request;
74struct xbdback_io; 74struct xbdback_io;
75struct xbdback_fragment; 75struct xbdback_fragment;
76struct xbdback_instance; 76struct xbdback_instance;
77 77
78/* state of a xbdback instance */ 78/* state of a xbdback instance */
79typedef enum {CONNECTED, DISCONNECTING, DISCONNECTED} xbdback_state_t; 79typedef enum {CONNECTED, DISCONNECTING, DISCONNECTED} xbdback_state_t;
80 80
81/* 81/*
82 * Since there are a variety of conditions that can block our I/O 82 * Since there are a variety of conditions that can block our I/O
83 * processing, which isn't allowed to suspend its thread's execution, 83 * processing, which isn't allowed to suspend its thread's execution,
84 * such things will be done in a sort of continuation-passing style. 84 * such things will be done in a sort of continuation-passing style.
85 *  85 *
86 * Return value is NULL to indicate that execution has blocked; if 86 * Return value is NULL to indicate that execution has blocked; if
87 * it's finished, set xbdi->xbdi_cont (see below) to NULL and the return 87 * it's finished, set xbdi->xbdi_cont (see below) to NULL and the return
88 * doesn't matter. Otherwise it's passed as the second parameter to 88 * doesn't matter. Otherwise it's passed as the second parameter to
89 * the new value of xbdi->xbdi_cont. 89 * the new value of xbdi->xbdi_cont.
90 * Here's how the call graph is supposed to be for a single I/O: 90 * Here's how the call graph is supposed to be for a single I/O:
91 * xbdback_co_main()  91 * xbdback_co_main()
92 * | |-> xbdback_co_cache_doflush() -> stall 92 * | |-> xbdback_co_cache_doflush() -> stall
93 * | xbdback_co_cache_flush2() <- xbdback_co_flush_done() <- 93 * | xbdback_co_cache_flush2() <- xbdback_co_flush_done() <-
94 * | | | 94 * | | |
95 * | |-> xbdback_co_cache_flush() -> xbdback_co_flush() -- 95 * | |-> xbdback_co_cache_flush() -> xbdback_co_flush() --
96 * xbdback_co_main_loop() -> xbdback_co_main_done() -> xbdback_co_flush() 96 * xbdback_co_main_loop() -> xbdback_co_main_done() -> xbdback_co_flush()
97 * | | | 97 * | | |
98 * | xbdback_co_main_done2() <- xbdback_co_flush_done() 98 * | xbdback_co_main_done2() <- xbdback_co_flush_done()
99 * | | 99 * | |
100 * | xbdback_co_main() or NULL 100 * | xbdback_co_main() or NULL
101 * xbdback_co_io() -> xbdback_co_main_incr() -> xbdback_co_main_loop() 101 * xbdback_co_io() -> xbdback_co_main_incr() -> xbdback_co_main_loop()
102 * | 102 * |
103 * xbdback_co_io_gotreq() -> xbdback_co_flush() -> xbdback_co_flush() 103 * xbdback_co_io_gotreq() -> xbdback_co_flush() -> xbdback_co_flush()
104 * | | | 104 * | | |
105 * xbdback_co_io_loop() --- <---------------- xbdback_co_flush_done() 105 * xbdback_co_io_loop() --- <---------------- xbdback_co_flush_done()
106 * | | 106 * | |
107 * xbdback_co_io_gotio() | 107 * xbdback_co_io_gotio() |
108 * | | 108 * | |
109 * xbdback_co_io_gotio2()<- 109 * xbdback_co_io_gotio2()<-
110 * | |--------> xbdback_co_io_gotfrag 110 * | |--------> xbdback_co_io_gotfrag
111 * | | 111 * | |
112 * xbdback_co_io_gotfrag2() <----------| 112 * xbdback_co_io_gotfrag2() <----------|
113 * | |--> xbdback_co_io_loop() 113 * | |--> xbdback_co_io_loop()
114 * xbdback_co_main_incr() 114 * xbdback_co_main_incr()
115 */ 115 */
116typedef void *(* xbdback_cont_t)(struct xbdback_instance *, void *); 116typedef void *(* xbdback_cont_t)(struct xbdback_instance *, void *);
117 117
118enum xbdi_proto { 118enum xbdi_proto {
119 XBDIP_NATIVE, 119 XBDIP_NATIVE,
120 XBDIP_32, 120 XBDIP_32,
121 XBDIP_64 121 XBDIP_64
122}; 122};
123 123
124 124
125/* we keep the xbdback instances in a linked list */ 125/* we keep the xbdback instances in a linked list */
126struct xbdback_instance { 126struct xbdback_instance {
127 SLIST_ENTRY(xbdback_instance) next; 127 SLIST_ENTRY(xbdback_instance) next;
128 struct xenbus_device *xbdi_xbusd; /* our xenstore entry */ 128 struct xenbus_device *xbdi_xbusd; /* our xenstore entry */
129 struct xenbus_watch xbdi_watch; /* to watch our store */ 129 struct xenbus_watch xbdi_watch; /* to watch our store */
130 domid_t xbdi_domid; /* attached to this domain */ 130 domid_t xbdi_domid; /* attached to this domain */
131 uint32_t xbdi_handle; /* domain-specific handle */ 131 uint32_t xbdi_handle; /* domain-specific handle */
132 xbdback_state_t xbdi_status; 132 xbdback_state_t xbdi_status;
133 /* backing device parameters */ 133 /* backing device parameters */
134 dev_t xbdi_dev; 134 dev_t xbdi_dev;
135 const struct bdevsw *xbdi_bdevsw; /* pointer to the device's bdevsw */ 135 const struct bdevsw *xbdi_bdevsw; /* pointer to the device's bdevsw */
136 struct vnode *xbdi_vp; 136 struct vnode *xbdi_vp;
137 uint64_t xbdi_size; 137 uint64_t xbdi_size;
138 int xbdi_ro; /* is device read-only ? */ 138 int xbdi_ro; /* is device read-only ? */
139 /* parameters for the communication */ 139 /* parameters for the communication */
140 unsigned int xbdi_evtchn; 140 unsigned int xbdi_evtchn;
141 /* private parameters for communication */ 141 /* private parameters for communication */
142 blkif_back_ring_proto_t xbdi_ring; 142 blkif_back_ring_proto_t xbdi_ring;
143 enum xbdi_proto xbdi_proto; 143 enum xbdi_proto xbdi_proto;
144 grant_handle_t xbdi_ring_handle; /* to unmap the ring */ 144 grant_handle_t xbdi_ring_handle; /* to unmap the ring */
145 vaddr_t xbdi_ring_va; /* to unmap the ring */ 145 vaddr_t xbdi_ring_va; /* to unmap the ring */
146 /* disconnection must be postponed until all I/O is done */ 146 /* disconnection must be postponed until all I/O is done */
147 int xbdi_refcnt; 147 int xbdi_refcnt;
148 /*  148 /*
149 * State for I/O processing/coalescing follows; this has to 149 * State for I/O processing/coalescing follows; this has to
150 * live here instead of on the stack because of the 150 * live here instead of on the stack because of the
151 * continuation-ness (see above). 151 * continuation-ness (see above).
152 */ 152 */
153 RING_IDX xbdi_req_prod; /* limit on request indices */ 153 RING_IDX xbdi_req_prod; /* limit on request indices */
154 xbdback_cont_t xbdi_cont, xbdi_cont_aux; 154 xbdback_cont_t xbdi_cont, xbdi_cont_aux;
155 SIMPLEQ_ENTRY(xbdback_instance) xbdi_on_hold; /* waiting on resources */ 155 SIMPLEQ_ENTRY(xbdback_instance) xbdi_on_hold; /* waiting on resources */
156 /* _request state */ 156 /* _request state */
157 struct xbdback_request *xbdi_req; /* if NULL, ignore following */ 157 struct xbdback_request *xbdi_req; /* if NULL, ignore following */
158 blkif_request_t xbdi_xen_req; 158 blkif_request_t xbdi_xen_req;
159 int xbdi_segno; 159 int xbdi_segno;
160 /* _io state */ 160 /* _io state */
161 struct xbdback_io *xbdi_io; /* if NULL, ignore next field */ 161 struct xbdback_io *xbdi_io; /* if NULL, ignore next field */
162 daddr_t xbdi_next_sector; 162 daddr_t xbdi_next_sector;
163 uint8_t xbdi_last_fs, xbdi_this_fs; /* first sectors */ 163 uint8_t xbdi_last_fs, xbdi_this_fs; /* first sectors */
164 uint8_t xbdi_last_ls, xbdi_this_ls; /* last sectors */ 164 uint8_t xbdi_last_ls, xbdi_this_ls; /* last sectors */
165 grant_ref_t xbdi_thisgrt, xbdi_lastgrt; /* grants */ 165 grant_ref_t xbdi_thisgrt, xbdi_lastgrt; /* grants */
166 /* other state */ 166 /* other state */
167 int xbdi_same_page; /* are we merging two segments on the same page? */ 167 int xbdi_same_page; /* are we merging two segments on the same page? */
168 uint xbdi_pendingreqs; /* number of I/O in fly */ 168 uint xbdi_pendingreqs; /* number of I/O in fly */
169}; 169};
170/* Manipulation of the above reference count. */ 170/* Manipulation of the above reference count. */
171#define xbdi_get(xbdip) atomic_inc_uint(&(xbdip)->xbdi_refcnt) 171#define xbdi_get(xbdip) atomic_inc_uint(&(xbdip)->xbdi_refcnt)
172#define xbdi_put(xbdip) \ 172#define xbdi_put(xbdip) \
173do { \ 173do { \
174 if (atomic_dec_uint_nv(&(xbdip)->xbdi_refcnt) == 0) \ 174 if (atomic_dec_uint_nv(&(xbdip)->xbdi_refcnt) == 0) \
175 xbdback_finish_disconnect(xbdip); \ 175 xbdback_finish_disconnect(xbdip); \
176} while (/* CONSTCOND */ 0) 176} while (/* CONSTCOND */ 0)
177 177
178SLIST_HEAD(, xbdback_instance) xbdback_instances; 178SLIST_HEAD(, xbdback_instance) xbdback_instances;
179 179
180/* 180/*
181 * For each request from a guest, a xbdback_request is allocated from 181 * For each request from a guest, a xbdback_request is allocated from
182 * a pool. This will describe the request until completion. The 182 * a pool. This will describe the request until completion. The
183 * request may require multiple IO operations to perform, so the 183 * request may require multiple IO operations to perform, so the
184 * per-IO information is not stored here. 184 * per-IO information is not stored here.
185 */ 185 */
186struct xbdback_request { 186struct xbdback_request {
187 struct xbdback_instance *rq_xbdi; /* our xbd instance */ 187 struct xbdback_instance *rq_xbdi; /* our xbd instance */
188 uint64_t rq_id; 188 uint64_t rq_id;
189 int rq_iocount; /* reference count; or, number of outstanding I/O's */ 189 int rq_iocount; /* reference count; or, number of outstanding I/O's */
190 int rq_ioerrs; 190 int rq_ioerrs;
191 uint8_t rq_operation; 191 uint8_t rq_operation;
192}; 192};
193 193
194/* 194/*
195 * For each I/O operation associated with one of those requests, an 195 * For each I/O operation associated with one of those requests, an
196 * xbdback_io is allocated from a pool. It may correspond to multiple 196 * xbdback_io is allocated from a pool. It may correspond to multiple
197 * Xen disk requests, or parts of them, if several arrive at once that 197 * Xen disk requests, or parts of them, if several arrive at once that
198 * can be coalesced. 198 * can be coalesced.
199 */ 199 */
200struct xbdback_io { 200struct xbdback_io {
201 struct work xio_work; 201 struct work xio_work;
202 /* The instance pointer is duplicated for convenience. */ 202 /* The instance pointer is duplicated for convenience. */
203 struct xbdback_instance *xio_xbdi; /* our xbd instance */ 203 struct xbdback_instance *xio_xbdi; /* our xbd instance */
204 uint8_t xio_operation; 204 uint8_t xio_operation;
205 union { 205 union {
206 struct { 206 struct {
207 struct buf xio_buf; /* our I/O */ 207 struct buf xio_buf; /* our I/O */
208 /* xbd requests involved */ 208 /* xbd requests involved */
209 SLIST_HEAD(, xbdback_fragment) xio_rq; 209 SLIST_HEAD(, xbdback_fragment) xio_rq;
210 /* the virtual address to map the request at */ 210 /* the virtual address to map the request at */
211 vaddr_t xio_vaddr; 211 vaddr_t xio_vaddr;
212 /* grants to map */ 212 /* grants to map */
213 grant_ref_t xio_gref[XENSHM_MAX_PAGES_PER_REQUEST]; 213 grant_ref_t xio_gref[XENSHM_MAX_PAGES_PER_REQUEST];
214 /* grants release */ 214 /* grants release */
215 grant_handle_t xio_gh[XENSHM_MAX_PAGES_PER_REQUEST]; 215 grant_handle_t xio_gh[XENSHM_MAX_PAGES_PER_REQUEST];
216 uint16_t xio_nrma; /* number of guest pages */ 216 uint16_t xio_nrma; /* number of guest pages */
217 uint16_t xio_mapped; 217 uint16_t xio_mapped;
218 } xio_rw; 218 } xio_rw;
219 uint64_t xio_flush_id; 219 uint64_t xio_flush_id;
220 } u; 220 } u;
221}; 221};
222#define xio_buf u.xio_rw.xio_buf 222#define xio_buf u.xio_rw.xio_buf
223#define xio_rq u.xio_rw.xio_rq 223#define xio_rq u.xio_rw.xio_rq
224#define xio_vaddr u.xio_rw.xio_vaddr 224#define xio_vaddr u.xio_rw.xio_vaddr
225#define xio_gref u.xio_rw.xio_gref 225#define xio_gref u.xio_rw.xio_gref
226#define xio_gh u.xio_rw.xio_gh 226#define xio_gh u.xio_rw.xio_gh
227#define xio_nrma u.xio_rw.xio_nrma 227#define xio_nrma u.xio_rw.xio_nrma
228#define xio_mapped u.xio_rw.xio_mapped 228#define xio_mapped u.xio_rw.xio_mapped
229 229
230#define xio_flush_id u.xio_flush_id 230#define xio_flush_id u.xio_flush_id
231 231
232/* 232/*
233 * Rather than have the xbdback_io keep an array of the 233 * Rather than have the xbdback_io keep an array of the
234 * xbdback_requests involved, since the actual number will probably be 234 * xbdback_requests involved, since the actual number will probably be
235 * small but might be as large as BLKIF_RING_SIZE, use a list. This 235 * small but might be as large as BLKIF_RING_SIZE, use a list. This
236 * would be threaded through xbdback_request, but one of them might be 236 * would be threaded through xbdback_request, but one of them might be
237 * part of multiple I/O's, alas. 237 * part of multiple I/O's, alas.
238 */ 238 */
239struct xbdback_fragment { 239struct xbdback_fragment {
240 struct xbdback_request *car; 240 struct xbdback_request *car;
241 SLIST_ENTRY(xbdback_fragment) cdr; 241 SLIST_ENTRY(xbdback_fragment) cdr;
242}; 242};
243 243
244/* 244/*
245 * Wrap our pools with a chain of xbdback_instances whose I/O 245 * Wrap our pools with a chain of xbdback_instances whose I/O
246 * processing has blocked for want of memory from that pool. 246 * processing has blocked for want of memory from that pool.
247 */ 247 */
248struct xbdback_pool { 248struct xbdback_pool {
249 struct pool p; 249 struct pool p;
250 SIMPLEQ_HEAD(xbdback_iqueue, xbdback_instance) q; 250 SIMPLEQ_HEAD(xbdback_iqueue, xbdback_instance) q;
251 struct timeval last_warning; 251 struct timeval last_warning;
252} xbdback_request_pool, xbdback_io_pool, xbdback_fragment_pool; 252} xbdback_request_pool, xbdback_io_pool, xbdback_fragment_pool;
253static struct xbdback_iqueue xbdback_shmq; 253static struct xbdback_iqueue xbdback_shmq;
254static int xbdback_shmcb; /* have we already registered a callback? */ 254static int xbdback_shmcb; /* have we already registered a callback? */
255 255
256struct timeval xbdback_poolsleep_intvl = { 5, 0 }; 256struct timeval xbdback_poolsleep_intvl = { 5, 0 };
257#ifdef DEBUG 257#ifdef DEBUG
258struct timeval xbdback_fragio_intvl = { 60, 0 }; 258struct timeval xbdback_fragio_intvl = { 60, 0 };
259#endif 259#endif
260 void xbdbackattach(int); 260 void xbdbackattach(int);
261static int xbdback_xenbus_create(struct xenbus_device *); 261static int xbdback_xenbus_create(struct xenbus_device *);
262static int xbdback_xenbus_destroy(void *); 262static int xbdback_xenbus_destroy(void *);
263static void xbdback_frontend_changed(void *, XenbusState); 263static void xbdback_frontend_changed(void *, XenbusState);
264static void xbdback_backend_changed(struct xenbus_watch *, 264static void xbdback_backend_changed(struct xenbus_watch *,
265 const char **, unsigned int); 265 const char **, unsigned int);
266static int xbdback_evthandler(void *); 266static int xbdback_evthandler(void *);
267static void xbdback_finish_disconnect(struct xbdback_instance *); 267static void xbdback_finish_disconnect(struct xbdback_instance *);
268 268
269static struct xbdback_instance *xbdif_lookup(domid_t, uint32_t); 269static struct xbdback_instance *xbdif_lookup(domid_t, uint32_t);
270 270
271static void *xbdback_co_main(struct xbdback_instance *, void *); 271static void *xbdback_co_main(struct xbdback_instance *, void *);
272static void *xbdback_co_main_loop(struct xbdback_instance *, void *); 272static void *xbdback_co_main_loop(struct xbdback_instance *, void *);
273static void *xbdback_co_main_incr(struct xbdback_instance *, void *); 273static void *xbdback_co_main_incr(struct xbdback_instance *, void *);
274static void *xbdback_co_main_done(struct xbdback_instance *, void *); 274static void *xbdback_co_main_done(struct xbdback_instance *, void *);
275static void *xbdback_co_main_done2(struct xbdback_instance *, void *); 275static void *xbdback_co_main_done2(struct xbdback_instance *, void *);
276 276
277static void *xbdback_co_cache_flush(struct xbdback_instance *, void *); 277static void *xbdback_co_cache_flush(struct xbdback_instance *, void *);
278static void *xbdback_co_cache_flush2(struct xbdback_instance *, void *); 278static void *xbdback_co_cache_flush2(struct xbdback_instance *, void *);
279static void *xbdback_co_cache_doflush(struct xbdback_instance *, void *); 279static void *xbdback_co_cache_doflush(struct xbdback_instance *, void *);
280 280
281static void *xbdback_co_io(struct xbdback_instance *, void *); 281static void *xbdback_co_io(struct xbdback_instance *, void *);
282static void *xbdback_co_io_gotreq(struct xbdback_instance *, void *); 282static void *xbdback_co_io_gotreq(struct xbdback_instance *, void *);
283static void *xbdback_co_io_loop(struct xbdback_instance *, void *); 283static void *xbdback_co_io_loop(struct xbdback_instance *, void *);
284static void *xbdback_co_io_gotio(struct xbdback_instance *, void *); 284static void *xbdback_co_io_gotio(struct xbdback_instance *, void *);
285static void *xbdback_co_io_gotio2(struct xbdback_instance *, void *); 285static void *xbdback_co_io_gotio2(struct xbdback_instance *, void *);
286static void *xbdback_co_io_gotfrag(struct xbdback_instance *, void *); 286static void *xbdback_co_io_gotfrag(struct xbdback_instance *, void *);
287static void *xbdback_co_io_gotfrag2(struct xbdback_instance *, void *); 287static void *xbdback_co_io_gotfrag2(struct xbdback_instance *, void *);
288 288
289static void *xbdback_co_flush(struct xbdback_instance *, void *); 289static void *xbdback_co_flush(struct xbdback_instance *, void *);
290static void *xbdback_co_flush_done(struct xbdback_instance *, void *); 290static void *xbdback_co_flush_done(struct xbdback_instance *, void *);
291 291
292static int xbdback_shm_callback(void *); 292static int xbdback_shm_callback(void *);
293static void xbdback_io_error(struct xbdback_io *, int); 293static void xbdback_io_error(struct xbdback_io *, int);
294static void xbdback_do_io(struct work *, void *); 294static void xbdback_do_io(struct work *, void *);
295static void xbdback_iodone(struct buf *); 295static void xbdback_iodone(struct buf *);
296static void xbdback_send_reply(struct xbdback_instance *, uint64_t , int , int); 296static void xbdback_send_reply(struct xbdback_instance *, uint64_t , int , int);
297 297
298static void *xbdback_map_shm(struct xbdback_io *); 298static void *xbdback_map_shm(struct xbdback_io *);
299static void xbdback_unmap_shm(struct xbdback_io *); 299static void xbdback_unmap_shm(struct xbdback_io *);
300 300
301static void *xbdback_pool_get(struct xbdback_pool *, 301static void *xbdback_pool_get(struct xbdback_pool *,
302 struct xbdback_instance *); 302 struct xbdback_instance *);
303static void xbdback_pool_put(struct xbdback_pool *, void *); 303static void xbdback_pool_put(struct xbdback_pool *, void *);
304static void xbdback_trampoline(struct xbdback_instance *, void *); 304static void xbdback_trampoline(struct xbdback_instance *, void *);
305 305
306static struct xenbus_backend_driver xbd_backend_driver = { 306static struct xenbus_backend_driver xbd_backend_driver = {
307 .xbakd_create = xbdback_xenbus_create, 307 .xbakd_create = xbdback_xenbus_create,
308 .xbakd_type = "vbd" 308 .xbakd_type = "vbd"
309}; 309};
310 310
311struct workqueue *xbdback_workqueue; 311struct workqueue *xbdback_workqueue;
312 312
313void 313void
314xbdbackattach(int n) 314xbdbackattach(int n)
315{ 315{
316 XENPRINTF(("xbdbackattach\n")); 316 XENPRINTF(("xbdbackattach\n"));
317 317
318 /* 318 /*
319 * initialize the backend driver, register the control message handler 319 * initialize the backend driver, register the control message handler
320 * and send driver up message. 320 * and send driver up message.
321 */ 321 */
322 SLIST_INIT(&xbdback_instances); 322 SLIST_INIT(&xbdback_instances);
323 SIMPLEQ_INIT(&xbdback_shmq); 323 SIMPLEQ_INIT(&xbdback_shmq);
324 xbdback_shmcb = 0; 324 xbdback_shmcb = 0;
325 pool_init(&xbdback_request_pool.p, sizeof(struct xbdback_request), 325 pool_init(&xbdback_request_pool.p, sizeof(struct xbdback_request),
326 0, 0, 0, "xbbrp", NULL, IPL_BIO); 326 0, 0, 0, "xbbrp", NULL, IPL_BIO);
327 SIMPLEQ_INIT(&xbdback_request_pool.q); 327 SIMPLEQ_INIT(&xbdback_request_pool.q);
328 pool_init(&xbdback_io_pool.p, sizeof(struct xbdback_io), 328 pool_init(&xbdback_io_pool.p, sizeof(struct xbdback_io),
329 0, 0, 0, "xbbip", NULL, IPL_BIO); 329 0, 0, 0, "xbbip", NULL, IPL_BIO);
330 SIMPLEQ_INIT(&xbdback_io_pool.q); 330 SIMPLEQ_INIT(&xbdback_io_pool.q);
331 pool_init(&xbdback_fragment_pool.p, sizeof(struct xbdback_fragment), 331 pool_init(&xbdback_fragment_pool.p, sizeof(struct xbdback_fragment),
332 0, 0, 0, "xbbfp", NULL, IPL_BIO); 332 0, 0, 0, "xbbfp", NULL, IPL_BIO);
333 SIMPLEQ_INIT(&xbdback_fragment_pool.q); 333 SIMPLEQ_INIT(&xbdback_fragment_pool.q);
334 /* we allocate enough to handle a whole ring at once */ 334 /* we allocate enough to handle a whole ring at once */
335 if (pool_prime(&xbdback_request_pool.p, BLKIF_RING_SIZE) != 0) 335 if (pool_prime(&xbdback_request_pool.p, BLKIF_RING_SIZE) != 0)
336 printf("xbdback: failed to prime request pool\n"); 336 printf("xbdback: failed to prime request pool\n");
337 if (pool_prime(&xbdback_io_pool.p, BLKIF_RING_SIZE) != 0) 337 if (pool_prime(&xbdback_io_pool.p, BLKIF_RING_SIZE) != 0)
338 printf("xbdback: failed to prime io pool\n"); 338 printf("xbdback: failed to prime io pool\n");
339 if (pool_prime(&xbdback_fragment_pool.p, 339 if (pool_prime(&xbdback_fragment_pool.p,
340 BLKIF_MAX_SEGMENTS_PER_REQUEST * BLKIF_RING_SIZE) != 0) 340 BLKIF_MAX_SEGMENTS_PER_REQUEST * BLKIF_RING_SIZE) != 0)
341 printf("xbdback: failed to prime fragment pool\n"); 341 printf("xbdback: failed to prime fragment pool\n");
342 342
343 if (workqueue_create(&xbdback_workqueue, "xbdbackd", 343 if (workqueue_create(&xbdback_workqueue, "xbdbackd",
344 xbdback_do_io, NULL, PRI_BIO, IPL_BIO, 0)) 344 xbdback_do_io, NULL, PRI_BIO, IPL_BIO, 0))
345 printf("xbdback: failed to init workqueue\n"); 345 printf("xbdback: failed to init workqueue\n");
346 xenbus_backend_register(&xbd_backend_driver); 346 xenbus_backend_register(&xbd_backend_driver);
347} 347}
348 348
349static int 349static int
350xbdback_xenbus_create(struct xenbus_device *xbusd) 350xbdback_xenbus_create(struct xenbus_device *xbusd)
351{ 351{
352 struct xbdback_instance *xbdi; 352 struct xbdback_instance *xbdi;
353 long domid, handle; 353 long domid, handle;
354 int error, i; 354 int error, i;
355 char *ep; 355 char *ep;
356 356
357 if ((error = xenbus_read_ul(NULL, xbusd->xbusd_path, 357 if ((error = xenbus_read_ul(NULL, xbusd->xbusd_path,
358 "frontend-id", &domid, 10)) != 0) { 358 "frontend-id", &domid, 10)) != 0) {
359 aprint_error("xbdback: can't read %s/frontend-id: %d\n", 359 aprint_error("xbdback: can't read %s/frontend-id: %d\n",
360 xbusd->xbusd_path, error); 360 xbusd->xbusd_path, error);
361 return error; 361 return error;
362 } 362 }
363 363
364 /* 364 /*
365 * get handle: this is the last component of the path; which is 365 * get handle: this is the last component of the path; which is
366 * a decimal number. $path/dev contains the device name, which is not 366 * a decimal number. $path/dev contains the device name, which is not
367 * appropriate. 367 * appropriate.
368 */ 368 */
369 for (i = strlen(xbusd->xbusd_path); i > 0; i--) { 369 for (i = strlen(xbusd->xbusd_path); i > 0; i--) {
370 if (xbusd->xbusd_path[i] == '/') 370 if (xbusd->xbusd_path[i] == '/')
371 break; 371 break;
372 } 372 }
373 if (i == 0) { 373 if (i == 0) {
374 aprint_error("xbdback: can't parse %s\n", 374 aprint_error("xbdback: can't parse %s\n",
375 xbusd->xbusd_path); 375 xbusd->xbusd_path);
376 return EFTYPE; 376 return EFTYPE;
377 } 377 }
378 handle = strtoul(&xbusd->xbusd_path[i+1], &ep, 10); 378 handle = strtoul(&xbusd->xbusd_path[i+1], &ep, 10);
379 if (*ep != '\0') { 379 if (*ep != '\0') {
380 aprint_error("xbdback: can't parse %s\n", 380 aprint_error("xbdback: can't parse %s\n",
381 xbusd->xbusd_path); 381 xbusd->xbusd_path);
382 return EFTYPE; 382 return EFTYPE;
383 } 383 }
384  384
385 if (xbdif_lookup(domid, handle) != NULL) { 385 if (xbdif_lookup(domid, handle) != NULL) {
386 return EEXIST; 386 return EEXIST;
387 } 387 }
388 xbdi = malloc(sizeof(struct xbdback_instance), M_DEVBUF, 388 xbdi = malloc(sizeof(struct xbdback_instance), M_DEVBUF,
389 M_NOWAIT | M_ZERO); 389 M_NOWAIT | M_ZERO);
390 if (xbdi == NULL) { 390 if (xbdi == NULL) {
391 return ENOMEM; 391 return ENOMEM;
392 } 392 }
393 xbdi->xbdi_domid = domid; 393 xbdi->xbdi_domid = domid;
394 xbdi->xbdi_handle = handle; 394 xbdi->xbdi_handle = handle;
395 xbdi->xbdi_status = DISCONNECTED; 395 xbdi->xbdi_status = DISCONNECTED;
396 xbdi->xbdi_refcnt = 1; 396 xbdi->xbdi_refcnt = 1;
397 SLIST_INSERT_HEAD(&xbdback_instances, xbdi, next); 397 SLIST_INSERT_HEAD(&xbdback_instances, xbdi, next);
398 xbusd->xbusd_u.b.b_cookie = xbdi;  398 xbusd->xbusd_u.b.b_cookie = xbdi;
399 xbusd->xbusd_u.b.b_detach = xbdback_xenbus_destroy; 399 xbusd->xbusd_u.b.b_detach = xbdback_xenbus_destroy;
400 xbusd->xbusd_otherend_changed = xbdback_frontend_changed; 400 xbusd->xbusd_otherend_changed = xbdback_frontend_changed;
401 xbdi->xbdi_xbusd = xbusd; 401 xbdi->xbdi_xbusd = xbusd;
402 402
403 error = xenbus_watch_path2(xbusd, xbusd->xbusd_path, "physical-device", 403 error = xenbus_watch_path2(xbusd, xbusd->xbusd_path, "physical-device",
404 &xbdi->xbdi_watch, xbdback_backend_changed); 404 &xbdi->xbdi_watch, xbdback_backend_changed);
405 if (error) { 405 if (error) {
406 printf("failed to watch on %s/physical-device: %d\n", 406 printf("failed to watch on %s/physical-device: %d\n",
407 xbusd->xbusd_path, error); 407 xbusd->xbusd_path, error);
408 goto fail; 408 goto fail;
409 } 409 }
410 xbdi->xbdi_watch.xbw_dev = xbusd; 410 xbdi->xbdi_watch.xbw_dev = xbusd;
411 error = xenbus_switch_state(xbusd, NULL, XenbusStateInitWait); 411 error = xenbus_switch_state(xbusd, NULL, XenbusStateInitWait);
412 if (error) { 412 if (error) {
413 printf("failed to switch state on %s: %d\n", 413 printf("failed to switch state on %s: %d\n",
414 xbusd->xbusd_path, error); 414 xbusd->xbusd_path, error);
415 goto fail2; 415 goto fail2;
416 } 416 }
417 return 0; 417 return 0;
418fail2: 418fail2:
419 unregister_xenbus_watch(&xbdi->xbdi_watch); 419 unregister_xenbus_watch(&xbdi->xbdi_watch);
420fail: 420fail:
421 free(xbdi, M_DEVBUF); 421 free(xbdi, M_DEVBUF);
422 return error; 422 return error;
423} 423}
424 424
425static int 425static int
426xbdback_xenbus_destroy(void *arg) 426xbdback_xenbus_destroy(void *arg)
427{ 427{
428 struct xbdback_instance *xbdi = arg; 428 struct xbdback_instance *xbdi = arg;
429 struct xenbus_device *xbusd = xbdi->xbdi_xbusd; 429 struct xenbus_device *xbusd = xbdi->xbdi_xbusd;
430 struct gnttab_unmap_grant_ref ungrop; 430 struct gnttab_unmap_grant_ref ungrop;
431 int err, s; 431 int err, s;
432 432
433 XENPRINTF(("xbdback_xenbus_destroy state %d\n", xbdi->xbdi_status)); 433 XENPRINTF(("xbdback_xenbus_destroy state %d\n", xbdi->xbdi_status));
434 434
435 if (xbdi->xbdi_status != DISCONNECTED) { 435 if (xbdi->xbdi_status != DISCONNECTED) {
436 hypervisor_mask_event(xbdi->xbdi_evtchn); 436 hypervisor_mask_event(xbdi->xbdi_evtchn);
437 event_remove_handler(xbdi->xbdi_evtchn, xbdback_evthandler, 437 event_remove_handler(xbdi->xbdi_evtchn, xbdback_evthandler,
438 xbdi); 438 xbdi);
439 xbdi->xbdi_status = DISCONNECTING; 439 xbdi->xbdi_status = DISCONNECTING;
440 s = splbio(); 440 s = splbio();
441 xbdi_put(xbdi); 441 xbdi_put(xbdi);
442 while (xbdi->xbdi_status != DISCONNECTED) { 442 while (xbdi->xbdi_status != DISCONNECTED) {
443 tsleep(&xbdi->xbdi_status, PRIBIO, "xbddis", 0); 443 tsleep(&xbdi->xbdi_status, PRIBIO, "xbddis", 0);
444 } 444 }
445 splx(s); 445 splx(s);
446 } 446 }
447 /* unregister watch */ 447 /* unregister watch */
448 if (xbdi->xbdi_watch.node) { 448 if (xbdi->xbdi_watch.node) {
449 unregister_xenbus_watch(&xbdi->xbdi_watch); 449 unregister_xenbus_watch(&xbdi->xbdi_watch);
450 free(xbdi->xbdi_watch.node, M_DEVBUF); 450 free(xbdi->xbdi_watch.node, M_DEVBUF);
451 xbdi->xbdi_watch.node = NULL; 451 xbdi->xbdi_watch.node = NULL;
452 } 452 }
453 /* unmap ring */ 453 /* unmap ring */
454 if (xbdi->xbdi_ring_va != 0) { 454 if (xbdi->xbdi_ring_va != 0) {
455 ungrop.host_addr = xbdi->xbdi_ring_va; 455 ungrop.host_addr = xbdi->xbdi_ring_va;
456 ungrop.handle = xbdi->xbdi_ring_handle; 456 ungrop.handle = xbdi->xbdi_ring_handle;
457 ungrop.dev_bus_addr = 0; 457 ungrop.dev_bus_addr = 0;
458 err = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, 458 err = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
459 &ungrop, 1); 459 &ungrop, 1);
460 if (err) 460 if (err)
461 printf("xbdback %s: unmap_grant_ref failed: %d\n", 461 printf("xbdback %s: unmap_grant_ref failed: %d\n",
462 xbusd->xbusd_otherend, err); 462 xbusd->xbusd_otherend, err);
463 uvm_km_free(kernel_map, xbdi->xbdi_ring_va, 463 uvm_km_free(kernel_map, xbdi->xbdi_ring_va,
464 PAGE_SIZE, UVM_KMF_VAONLY); 464 PAGE_SIZE, UVM_KMF_VAONLY);
465 } 465 }
466 /* close device */ 466 /* close device */
467 if (xbdi->xbdi_size) { 467 if (xbdi->xbdi_size) {
468 printf("xbd backend: detach device %s%"PRId32"%c for domain %d\n", 468 printf("xbd backend: detach device %s%"PRId32"%c for domain %d\n",
469 devsw_blk2name(major(xbdi->xbdi_dev)), 469 devsw_blk2name(major(xbdi->xbdi_dev)),
470 DISKUNIT(xbdi->xbdi_dev), 470 DISKUNIT(xbdi->xbdi_dev),
471 (char)DISKPART(xbdi->xbdi_dev) + 'a', 471 (char)DISKPART(xbdi->xbdi_dev) + 'a',
472 xbdi->xbdi_domid); 472 xbdi->xbdi_domid);
473 vn_close(xbdi->xbdi_vp, FREAD, NOCRED); 473 vn_close(xbdi->xbdi_vp, FREAD, NOCRED);
474 } 474 }
475 SLIST_REMOVE(&xbdback_instances, xbdi, xbdback_instance, next); 475 SLIST_REMOVE(&xbdback_instances, xbdi, xbdback_instance, next);
476 free(xbdi, M_DEVBUF); 476 free(xbdi, M_DEVBUF);
477 return 0; 477 return 0;
478} 478}
479 479
480static int 480static int
481xbdback_connect(struct xbdback_instance *xbdi) 481xbdback_connect(struct xbdback_instance *xbdi)
482{ 482{
483 int len, err; 483 int len, err;
484 struct gnttab_map_grant_ref grop; 484 struct gnttab_map_grant_ref grop;
485 struct gnttab_unmap_grant_ref ungrop; 485 struct gnttab_unmap_grant_ref ungrop;
486 evtchn_op_t evop; 486 evtchn_op_t evop;
487 u_long ring_ref, revtchn; 487 u_long ring_ref, revtchn;
488 char *xsproto; 488 char *xsproto;
489 char evname[16]; 489 char evname[16];
490 const char *proto; 490 const char *proto;
491 struct xenbus_device *xbusd = xbdi->xbdi_xbusd; 491 struct xenbus_device *xbusd = xbdi->xbdi_xbusd;
492 492
493 /* read comunication informations */ 493 /* read comunication informations */
494 err = xenbus_read_ul(NULL, xbusd->xbusd_otherend, 494 err = xenbus_read_ul(NULL, xbusd->xbusd_otherend,
495 "ring-ref", &ring_ref, 10); 495 "ring-ref", &ring_ref, 10);
496 if (err) { 496 if (err) {
497 xenbus_dev_fatal(xbusd, err, "reading %s/ring-ref", 497 xenbus_dev_fatal(xbusd, err, "reading %s/ring-ref",
498 xbusd->xbusd_otherend); 498 xbusd->xbusd_otherend);
499 return -1; 499 return -1;
500 } 500 }
501 err = xenbus_read_ul(NULL, xbusd->xbusd_otherend, 501 err = xenbus_read_ul(NULL, xbusd->xbusd_otherend,
502 "event-channel", &revtchn, 10); 502 "event-channel", &revtchn, 10);
503 if (err) { 503 if (err) {
504 xenbus_dev_fatal(xbusd, err, "reading %s/event-channel", 504 xenbus_dev_fatal(xbusd, err, "reading %s/event-channel",
505 xbusd->xbusd_otherend); 505 xbusd->xbusd_otherend);
506 return -1; 506 return -1;
507 } 507 }
508 err = xenbus_read(NULL, xbusd->xbusd_otherend, "protocol", 508 err = xenbus_read(NULL, xbusd->xbusd_otherend, "protocol",
509 &len, &xsproto); 509 &len, &xsproto);
510 if (err) { 510 if (err) {
511 xbdi->xbdi_proto = XBDIP_NATIVE; 511 xbdi->xbdi_proto = XBDIP_NATIVE;
512 proto = "unspecified"; 512 proto = "unspecified";
513 } else { 513 } else {
514 if (strcmp(xsproto, XEN_IO_PROTO_ABI_NATIVE) == 0) { 514 if (strcmp(xsproto, XEN_IO_PROTO_ABI_NATIVE) == 0) {
515 xbdi->xbdi_proto = XBDIP_NATIVE; 515 xbdi->xbdi_proto = XBDIP_NATIVE;
516 proto = XEN_IO_PROTO_ABI_NATIVE; 516 proto = XEN_IO_PROTO_ABI_NATIVE;
517 } else if (strcmp(xsproto, XEN_IO_PROTO_ABI_X86_32) == 0) { 517 } else if (strcmp(xsproto, XEN_IO_PROTO_ABI_X86_32) == 0) {
518 xbdi->xbdi_proto = XBDIP_32; 518 xbdi->xbdi_proto = XBDIP_32;
519 proto = XEN_IO_PROTO_ABI_X86_32; 519 proto = XEN_IO_PROTO_ABI_X86_32;
520 } else if (strcmp(xsproto, XEN_IO_PROTO_ABI_X86_64) == 0) { 520 } else if (strcmp(xsproto, XEN_IO_PROTO_ABI_X86_64) == 0) {
521 xbdi->xbdi_proto = XBDIP_64; 521 xbdi->xbdi_proto = XBDIP_64;
522 proto = XEN_IO_PROTO_ABI_X86_64; 522 proto = XEN_IO_PROTO_ABI_X86_64;
523 } else { 523 } else {
524 aprint_error("xbd domain %d: unknown proto %s\n", 524 aprint_error("xbd domain %d: unknown proto %s\n",
525 xbdi->xbdi_domid, xsproto); 525 xbdi->xbdi_domid, xsproto);
526 free(xsproto, M_DEVBUF); 526 free(xsproto, M_DEVBUF);
527 return -1; 527 return -1;
528 } 528 }
529 } 529 }
530 free(xsproto, M_DEVBUF); 530 free(xsproto, M_DEVBUF);
531 531
532 /* allocate VA space and map rings */ 532 /* allocate VA space and map rings */
533 xbdi->xbdi_ring_va = uvm_km_alloc(kernel_map, PAGE_SIZE, 0, 533 xbdi->xbdi_ring_va = uvm_km_alloc(kernel_map, PAGE_SIZE, 0,
534 UVM_KMF_VAONLY); 534 UVM_KMF_VAONLY);
535 if (xbdi->xbdi_ring_va == 0) { 535 if (xbdi->xbdi_ring_va == 0) {
536 xenbus_dev_fatal(xbusd, ENOMEM, 536 xenbus_dev_fatal(xbusd, ENOMEM,
537 "can't get VA for ring", xbusd->xbusd_otherend); 537 "can't get VA for ring", xbusd->xbusd_otherend);
538 return -1; 538 return -1;
539 } 539 }
540 540
541 grop.host_addr = xbdi->xbdi_ring_va; 541 grop.host_addr = xbdi->xbdi_ring_va;
542 grop.flags = GNTMAP_host_map; 542 grop.flags = GNTMAP_host_map;
543 grop.ref = ring_ref; 543 grop.ref = ring_ref;
544 grop.dom = xbdi->xbdi_domid; 544 grop.dom = xbdi->xbdi_domid;
545 err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, 545 err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref,
546 &grop, 1); 546 &grop, 1);
547 if (err || grop.status) { 547 if (err || grop.status) {
548 aprint_error("xbdback %s: can't map grant ref: %d/%d\n", 548 aprint_error("xbdback %s: can't map grant ref: %d/%d\n",
549 xbusd->xbusd_path, err, grop.status); 549 xbusd->xbusd_path, err, grop.status);
550 xenbus_dev_fatal(xbusd, EINVAL, 550 xenbus_dev_fatal(xbusd, EINVAL,
551 "can't map ring", xbusd->xbusd_otherend); 551 "can't map ring", xbusd->xbusd_otherend);
552 goto err; 552 goto err;
553 } 553 }
554 xbdi->xbdi_ring_handle = grop.handle; 554 xbdi->xbdi_ring_handle = grop.handle;
555 555
556 switch(xbdi->xbdi_proto) { 556 switch(xbdi->xbdi_proto) {
557 case XBDIP_NATIVE: 557 case XBDIP_NATIVE:
558 { 558 {
559 blkif_sring_t *sring = (void *)xbdi->xbdi_ring_va; 559 blkif_sring_t *sring = (void *)xbdi->xbdi_ring_va;
560 BACK_RING_INIT(&xbdi->xbdi_ring.ring_n, sring, PAGE_SIZE); 560 BACK_RING_INIT(&xbdi->xbdi_ring.ring_n, sring, PAGE_SIZE);
561 break; 561 break;
562 } 562 }
563 case XBDIP_32: 563 case XBDIP_32:
564 { 564 {
565 blkif_x86_32_sring_t *sring = (void *)xbdi->xbdi_ring_va; 565 blkif_x86_32_sring_t *sring = (void *)xbdi->xbdi_ring_va;
566 BACK_RING_INIT(&xbdi->xbdi_ring.ring_32, sring, PAGE_SIZE); 566 BACK_RING_INIT(&xbdi->xbdi_ring.ring_32, sring, PAGE_SIZE);
567 break; 567 break;
568 } 568 }
569 case XBDIP_64: 569 case XBDIP_64:
570 { 570 {
571 blkif_x86_64_sring_t *sring = (void *)xbdi->xbdi_ring_va; 571 blkif_x86_64_sring_t *sring = (void *)xbdi->xbdi_ring_va;
572 BACK_RING_INIT(&xbdi->xbdi_ring.ring_64, sring, PAGE_SIZE); 572 BACK_RING_INIT(&xbdi->xbdi_ring.ring_64, sring, PAGE_SIZE);
573 break; 573 break;
574 } 574 }
575 } 575 }
576 576
577 evop.cmd = EVTCHNOP_bind_interdomain; 577 evop.cmd = EVTCHNOP_bind_interdomain;
578 evop.u.bind_interdomain.remote_dom = xbdi->xbdi_domid; 578 evop.u.bind_interdomain.remote_dom = xbdi->xbdi_domid;
579 evop.u.bind_interdomain.remote_port = revtchn; 579 evop.u.bind_interdomain.remote_port = revtchn;
580 err = HYPERVISOR_event_channel_op(&evop); 580 err = HYPERVISOR_event_channel_op(&evop);
581 if (err) { 581 if (err) {
582 aprint_error("blkback %s: " 582 aprint_error("blkback %s: "
583 "can't get event channel: %d\n", 583 "can't get event channel: %d\n",
584 xbusd->xbusd_otherend, err); 584 xbusd->xbusd_otherend, err);
585 xenbus_dev_fatal(xbusd, err, 585 xenbus_dev_fatal(xbusd, err,
586 "can't bind event channel", xbusd->xbusd_otherend); 586 "can't bind event channel", xbusd->xbusd_otherend);
587 goto err2; 587 goto err2;
588 } 588 }
589 xbdi->xbdi_evtchn = evop.u.bind_interdomain.local_port; 589 xbdi->xbdi_evtchn = evop.u.bind_interdomain.local_port;
590 590
591 snprintf(evname, sizeof(evname), "xbd%d.%d", 591 snprintf(evname, sizeof(evname), "xbdback%di%d",
592 xbdi->xbdi_domid, xbdi->xbdi_handle); 592 xbdi->xbdi_domid, xbdi->xbdi_handle);
593 event_set_handler(xbdi->xbdi_evtchn, xbdback_evthandler, 593 event_set_handler(xbdi->xbdi_evtchn, xbdback_evthandler,
594 xbdi, IPL_BIO, evname); 594 xbdi, IPL_BIO, evname);
595 aprint_verbose("xbd backend 0x%x for domain %d " 595 aprint_verbose("xbd backend domain %d handle %#x (%d) "
596 "using event channel %d, protocol %s\n", xbdi->xbdi_handle, 596 "using event channel %d, protocol %s\n", xbdi->xbdi_domid,
597 xbdi->xbdi_domid, xbdi->xbdi_evtchn, proto); 597 xbdi->xbdi_handle, xbdi->xbdi_handle, xbdi->xbdi_evtchn, proto);
598 hypervisor_enable_event(xbdi->xbdi_evtchn); 598 hypervisor_enable_event(xbdi->xbdi_evtchn);
599 hypervisor_notify_via_evtchn(xbdi->xbdi_evtchn); 599 hypervisor_notify_via_evtchn(xbdi->xbdi_evtchn);
600 xbdi->xbdi_status = CONNECTED; 600 xbdi->xbdi_status = CONNECTED;
601 return 0; 601 return 0;
602 602
603err2: 603err2:
604 /* unmap ring */ 604 /* unmap ring */
605 ungrop.host_addr = xbdi->xbdi_ring_va; 605 ungrop.host_addr = xbdi->xbdi_ring_va;
606 ungrop.handle = xbdi->xbdi_ring_handle; 606 ungrop.handle = xbdi->xbdi_ring_handle;
607 ungrop.dev_bus_addr = 0; 607 ungrop.dev_bus_addr = 0;
608 err = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, 608 err = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
609 &ungrop, 1); 609 &ungrop, 1);
610 if (err) 610 if (err)
611 aprint_error("xbdback %s: unmap_grant_ref failed: %d\n", 611 aprint_error("xbdback %s: unmap_grant_ref failed: %d\n",
612 xbusd->xbusd_path, err); 612 xbusd->xbusd_path, err);
613 613
614err: 614err:
615 /* free ring VA space */ 615 /* free ring VA space */
616 uvm_km_free(kernel_map, xbdi->xbdi_ring_va, PAGE_SIZE, UVM_KMF_VAONLY); 616 uvm_km_free(kernel_map, xbdi->xbdi_ring_va, PAGE_SIZE, UVM_KMF_VAONLY);
617 return -1; 617 return -1;
618} 618}
619 619
620static void 620static void
621xbdback_frontend_changed(void *arg, XenbusState new_state) 621xbdback_frontend_changed(void *arg, XenbusState new_state)
622{ 622{
623 struct xbdback_instance *xbdi = arg; 623 struct xbdback_instance *xbdi = arg;
624 struct xenbus_device *xbusd = xbdi->xbdi_xbusd; 624 struct xenbus_device *xbusd = xbdi->xbdi_xbusd;
625 int s; 625 int s;
626 626
627 XENPRINTF(("xbdback %s: new state %d\n", xbusd->xbusd_path, new_state)); 627 XENPRINTF(("xbdback %s: new state %d\n", xbusd->xbusd_path, new_state));
628 switch(new_state) { 628 switch(new_state) {
629 case XenbusStateInitialising: 629 case XenbusStateInitialising:
630 break; 630 break;
631 case XenbusStateInitialised: 631 case XenbusStateInitialised:
632 case XenbusStateConnected: 632 case XenbusStateConnected:
633 if (xbdi->xbdi_status == CONNECTED) 633 if (xbdi->xbdi_status == CONNECTED)
634 break; 634 break;
635 xbdback_connect(xbdi); 635 xbdback_connect(xbdi);
636 break; 636 break;
637 case XenbusStateClosing: 637 case XenbusStateClosing:
638 hypervisor_mask_event(xbdi->xbdi_evtchn); 638 hypervisor_mask_event(xbdi->xbdi_evtchn);
639 event_remove_handler(xbdi->xbdi_evtchn, xbdback_evthandler, 639 event_remove_handler(xbdi->xbdi_evtchn, xbdback_evthandler,
640 xbdi); 640 xbdi);
641 xbdi->xbdi_status = DISCONNECTING; 641 xbdi->xbdi_status = DISCONNECTING;
642 s = splbio(); 642 s = splbio();
643 xbdi_put(xbdi); 643 xbdi_put(xbdi);
644 while (xbdi->xbdi_status != DISCONNECTED) { 644 while (xbdi->xbdi_status != DISCONNECTED) {
645 tsleep(&xbdi->xbdi_status, PRIBIO, "xbddis", 0); 645 tsleep(&xbdi->xbdi_status, PRIBIO, "xbddis", 0);
646 } 646 }
647 splx(s); 647 splx(s);
648 xenbus_switch_state(xbusd, NULL, XenbusStateClosing); 648 xenbus_switch_state(xbusd, NULL, XenbusStateClosing);
649 break; 649 break;
650 case XenbusStateClosed: 650 case XenbusStateClosed:
651 /* otherend_changed() should handle it for us */ 651 /* otherend_changed() should handle it for us */
652 panic("xbdback_frontend_changed: closed\n"); 652 panic("xbdback_frontend_changed: closed\n");
653 case XenbusStateUnknown: 653 case XenbusStateUnknown:
654 case XenbusStateInitWait: 654 case XenbusStateInitWait:
655 default: 655 default:
656 aprint_error("xbdback %s: invalid frontend state %d\n", 656 aprint_error("xbdback %s: invalid frontend state %d\n",
657 xbusd->xbusd_path, new_state); 657 xbusd->xbusd_path, new_state);
658 } 658 }
659 return; 659 return;
660} 660}
661 661
662static void 662static void
663xbdback_backend_changed(struct xenbus_watch *watch, 663xbdback_backend_changed(struct xenbus_watch *watch,
664 const char **vec, unsigned int len) 664 const char **vec, unsigned int len)
665{ 665{
666 struct xenbus_device *xbusd = watch->xbw_dev; 666 struct xenbus_device *xbusd = watch->xbw_dev;
667 struct xbdback_instance *xbdi = xbusd->xbusd_u.b.b_cookie; 667 struct xbdback_instance *xbdi = xbusd->xbusd_u.b.b_cookie;
668 int err; 668 int err;
669 long dev; 669 long dev;
670 char *mode; 670 char *mode;
671 struct xenbus_transaction *xbt; 671 struct xenbus_transaction *xbt;
672 const char *devname; 672 const char *devname;
673 int major; 673 int major;
674 674
675 err = xenbus_read_ul(NULL, xbusd->xbusd_path, "physical-device", 675 err = xenbus_read_ul(NULL, xbusd->xbusd_path, "physical-device",
676 &dev, 10); 676 &dev, 10);
677 /* 677 /*
678 * An error can occur as the watch can fire up just after being 678 * An error can occur as the watch can fire up just after being
679 * registered. So we have to ignore error :( 679 * registered. So we have to ignore error :(
680 */ 680 */
681 if (err) 681 if (err)
682 return; 682 return;
683 if (xbdi->xbdi_status == CONNECTED && xbdi->xbdi_dev != dev) { 683 if (xbdi->xbdi_status == CONNECTED && xbdi->xbdi_dev != dev) {
684 printf("xbdback %s: changing physical device from 0x%"PRIx64 684 printf("xbdback %s: changing physical device from 0x%"PRIx64
685 " to 0x%lx not supported\n", 685 " to 0x%lx not supported\n",
686 xbusd->xbusd_path, xbdi->xbdi_dev, dev); 686 xbusd->xbusd_path, xbdi->xbdi_dev, dev);
687 return; 687 return;
688 } 688 }
689 xbdi->xbdi_dev = dev; 689 xbdi->xbdi_dev = dev;
690 err = xenbus_read(NULL, xbusd->xbusd_path, "mode", NULL, &mode); 690 err = xenbus_read(NULL, xbusd->xbusd_path, "mode", NULL, &mode);
691 if (err) { 691 if (err) {
692 printf("xbdback: failed to read %s/mode: %d\n", 692 printf("xbdback: failed to read %s/mode: %d\n",
693 xbusd->xbusd_path, err); 693 xbusd->xbusd_path, err);
694 return; 694 return;
695 } 695 }
696 if (mode[0] == 'w') 696 if (mode[0] == 'w')
697 xbdi->xbdi_ro = 0; 697 xbdi->xbdi_ro = 0;
698 else 698 else
699 xbdi->xbdi_ro = 1; 699 xbdi->xbdi_ro = 1;
700 major = major(xbdi->xbdi_dev); 700 major = major(xbdi->xbdi_dev);
701 devname = devsw_blk2name(major); 701 devname = devsw_blk2name(major);
702 if (devname == NULL) { 702 if (devname == NULL) {
703 printf("xbdback %s: unknown device 0x%"PRIx64"\n", 703 printf("xbdback %s: unknown device 0x%"PRIx64"\n",
704 xbusd->xbusd_path, xbdi->xbdi_dev); 704 xbusd->xbusd_path, xbdi->xbdi_dev);
705 return; 705 return;
706 } 706 }
707 xbdi->xbdi_bdevsw = bdevsw_lookup(xbdi->xbdi_dev); 707 xbdi->xbdi_bdevsw = bdevsw_lookup(xbdi->xbdi_dev);
708 if (xbdi->xbdi_bdevsw == NULL) { 708 if (xbdi->xbdi_bdevsw == NULL) {
709 printf("xbdback %s: no bdevsw for device 0x%"PRIx64"\n", 709 printf("xbdback %s: no bdevsw for device 0x%"PRIx64"\n",
710 xbusd->xbusd_path, xbdi->xbdi_dev); 710 xbusd->xbusd_path, xbdi->xbdi_dev);
711 return; 711 return;
712 } 712 }
713 err = bdevvp(xbdi->xbdi_dev, &xbdi->xbdi_vp); 713 err = bdevvp(xbdi->xbdi_dev, &xbdi->xbdi_vp);
714 if (err) { 714 if (err) {
715 printf("xbdback %s: can't open device 0x%"PRIx64": %d\n", 715 printf("xbdback %s: can't open device 0x%"PRIx64": %d\n",
716 xbusd->xbusd_path, xbdi->xbdi_dev, err); 716 xbusd->xbusd_path, xbdi->xbdi_dev, err);
717 return; 717 return;
718 } 718 }
719 err = vn_lock(xbdi->xbdi_vp, LK_EXCLUSIVE | LK_RETRY); 719 err = vn_lock(xbdi->xbdi_vp, LK_EXCLUSIVE | LK_RETRY);
720 if (err) { 720 if (err) {
721 printf("xbdback %s: can't vn_lock device 0x%"PRIx64": %d\n", 721 printf("xbdback %s: can't vn_lock device 0x%"PRIx64": %d\n",
722 xbusd->xbusd_path, xbdi->xbdi_dev, err); 722 xbusd->xbusd_path, xbdi->xbdi_dev, err);
723 vrele(xbdi->xbdi_vp); 723 vrele(xbdi->xbdi_vp);
724 return; 724 return;
725 } 725 }
726 err = VOP_OPEN(xbdi->xbdi_vp, FREAD, NOCRED); 726 err = VOP_OPEN(xbdi->xbdi_vp, FREAD, NOCRED);
727 if (err) { 727 if (err) {
728 printf("xbdback %s: can't VOP_OPEN device 0x%"PRIx64": %d\n", 728 printf("xbdback %s: can't VOP_OPEN device 0x%"PRIx64": %d\n",
729 xbusd->xbusd_path, xbdi->xbdi_dev, err); 729 xbusd->xbusd_path, xbdi->xbdi_dev, err);
730 vput(xbdi->xbdi_vp); 730 vput(xbdi->xbdi_vp);
731 return; 731 return;
732 } 732 }
733 VOP_UNLOCK(xbdi->xbdi_vp); 733 VOP_UNLOCK(xbdi->xbdi_vp);
734 734
735 /* dk device; get wedge data */ 735 /* dk device; get wedge data */
736 struct dkwedge_info wi; 736 struct dkwedge_info wi;
737 if ((err = VOP_IOCTL(xbdi->xbdi_vp, DIOCGWEDGEINFO, &wi, 737 if ((err = VOP_IOCTL(xbdi->xbdi_vp, DIOCGWEDGEINFO, &wi,
738 FREAD, NOCRED)) == 0) { 738 FREAD, NOCRED)) == 0) {
739 xbdi->xbdi_size = wi.dkw_size; 739 xbdi->xbdi_size = wi.dkw_size;
740 printf("xbd backend: attach device %s (size %" PRIu64 ") " 740 printf("xbd backend: attach device %s (size %" PRIu64 ") "
741 "for domain %d\n", wi.dkw_devname, xbdi->xbdi_size, 741 "for domain %d\n", wi.dkw_devname, xbdi->xbdi_size,
742 xbdi->xbdi_domid); 742 xbdi->xbdi_domid);
743 } else { 743 } else {
744 /* disk device, get partition data */ 744 /* disk device, get partition data */
745 struct partinfo dpart; 745 struct partinfo dpart;
746 if ((err = VOP_IOCTL(xbdi->xbdi_vp, DIOCGPART, &dpart, 746 if ((err = VOP_IOCTL(xbdi->xbdi_vp, DIOCGPART, &dpart,
747 FREAD, 0)) == 0) { 747 FREAD, 0)) == 0) {
748 xbdi->xbdi_size = dpart.part->p_size; 748 xbdi->xbdi_size = dpart.part->p_size;
749 printf("xbd backend: attach device %s%"PRId32 749 printf("xbd backend: attach device %s%"PRId32
750 "%c (size %" PRIu64 ") for domain %d\n", 750 "%c (size %" PRIu64 ") for domain %d\n",
751 devname, DISKUNIT(xbdi->xbdi_dev), 751 devname, DISKUNIT(xbdi->xbdi_dev),
752 (char)DISKPART(xbdi->xbdi_dev) + 'a', xbdi->xbdi_size, 752 (char)DISKPART(xbdi->xbdi_dev) + 'a', xbdi->xbdi_size,
753 xbdi->xbdi_domid); 753 xbdi->xbdi_domid);
754 } 754 }
755 } 755 }
756 756
757 if (err != 0) { 757 if (err != 0) {
758 /* If both Ioctls failed set device size to 0 and return */ 758 /* If both Ioctls failed set device size to 0 and return */
759 printf("xbdback %s: can't DIOCGWEDGEINFO device " 759 printf("xbdback %s: can't DIOCGWEDGEINFO device "
760 "0x%"PRIx64": %d\n", xbusd->xbusd_path, 760 "0x%"PRIx64": %d\n", xbusd->xbusd_path,
761 xbdi->xbdi_dev, err);  761 xbdi->xbdi_dev, err);
762 xbdi->xbdi_size = xbdi->xbdi_dev = 0; 762 xbdi->xbdi_size = xbdi->xbdi_dev = 0;
763 vn_close(xbdi->xbdi_vp, FREAD, NOCRED); 763 vn_close(xbdi->xbdi_vp, FREAD, NOCRED);
764 xbdi->xbdi_vp = NULL; 764 xbdi->xbdi_vp = NULL;
765 return; 765 return;
766 } 766 }
767again: 767again:
768 xbt = xenbus_transaction_start(); 768 xbt = xenbus_transaction_start();
769 if (xbt == NULL) { 769 if (xbt == NULL) {
770 printf("xbdback %s: can't start transaction\n", 770 printf("xbdback %s: can't start transaction\n",
771 xbusd->xbusd_path); 771 xbusd->xbusd_path);
772 return; 772 return;
773 } 773 }
774 err = xenbus_printf(xbt, xbusd->xbusd_path, "sectors", "%" PRIu64 , 774 err = xenbus_printf(xbt, xbusd->xbusd_path, "sectors", "%" PRIu64 ,
775 xbdi->xbdi_size); 775 xbdi->xbdi_size);
776 if (err) { 776 if (err) {
777 printf("xbdback: failed to write %s/sectors: %d\n", 777 printf("xbdback: failed to write %s/sectors: %d\n",
778 xbusd->xbusd_path, err); 778 xbusd->xbusd_path, err);
779 goto abort; 779 goto abort;
780 } 780 }
781 err = xenbus_printf(xbt, xbusd->xbusd_path, "info", "%u", 781 err = xenbus_printf(xbt, xbusd->xbusd_path, "info", "%u",
782 xbdi->xbdi_ro ? VDISK_READONLY : 0); 782 xbdi->xbdi_ro ? VDISK_READONLY : 0);
783 if (err) { 783 if (err) {
784 printf("xbdback: failed to write %s/info: %d\n", 784 printf("xbdback: failed to write %s/info: %d\n",
785 xbusd->xbusd_path, err); 785 xbusd->xbusd_path, err);
786 goto abort; 786 goto abort;
787 } 787 }
788 err = xenbus_printf(xbt, xbusd->xbusd_path, "sector-size", "%lu", 788 err = xenbus_printf(xbt, xbusd->xbusd_path, "sector-size", "%lu",
789 (u_long)DEV_BSIZE); 789 (u_long)DEV_BSIZE);
790 if (err) { 790 if (err) {
791 printf("xbdback: failed to write %s/sector-size: %d\n", 791 printf("xbdback: failed to write %s/sector-size: %d\n",
792 xbusd->xbusd_path, err); 792 xbusd->xbusd_path, err);
793 goto abort; 793 goto abort;
794 } 794 }
795 err = xenbus_printf(xbt, xbusd->xbusd_path, "feature-flush-cache", 795 err = xenbus_printf(xbt, xbusd->xbusd_path, "feature-flush-cache",
796 "%u", 1); 796 "%u", 1);
797 if (err) { 797 if (err) {
798 printf("xbdback: failed to write %s/feature-flush-cache: %d\n", 798 printf("xbdback: failed to write %s/feature-flush-cache: %d\n",
799 xbusd->xbusd_path, err); 799 xbusd->xbusd_path, err);
800 goto abort; 800 goto abort;
801 } 801 }
802 err = xenbus_transaction_end(xbt, 0); 802 err = xenbus_transaction_end(xbt, 0);
803 if (err == EAGAIN) 803 if (err == EAGAIN)
804 goto again; 804 goto again;
805 if (err) { 805 if (err) {
806 printf("xbdback %s: can't end transaction: %d\n", 806 printf("xbdback %s: can't end transaction: %d\n",
807 xbusd->xbusd_path, err); 807 xbusd->xbusd_path, err);
808 } 808 }
809 err = xenbus_switch_state(xbusd, NULL, XenbusStateConnected); 809 err = xenbus_switch_state(xbusd, NULL, XenbusStateConnected);
810 if (err) { 810 if (err) {
811 printf("xbdback %s: can't switch state: %d\n", 811 printf("xbdback %s: can't switch state: %d\n",
812 xbusd->xbusd_path, err); 812 xbusd->xbusd_path, err);
813 } 813 }
814 return; 814 return;
815abort: 815abort:
816 xenbus_transaction_end(xbt, 1); 816 xenbus_transaction_end(xbt, 1);
817} 817}
818 818
819 819
820static void xbdback_finish_disconnect(struct xbdback_instance *xbdi) 820static void xbdback_finish_disconnect(struct xbdback_instance *xbdi)
821{ 821{
822 KASSERT(xbdi->xbdi_status == DISCONNECTING); 822 KASSERT(xbdi->xbdi_status == DISCONNECTING);
823 823
824 xbdi->xbdi_status = DISCONNECTED; 824 xbdi->xbdi_status = DISCONNECTED;
825 wakeup(&xbdi->xbdi_status); 825 wakeup(&xbdi->xbdi_status);
826 826
827} 827}
828 828
829static struct xbdback_instance * 829static struct xbdback_instance *
830xbdif_lookup(domid_t dom , uint32_t handle) 830xbdif_lookup(domid_t dom , uint32_t handle)
831{ 831{
832 struct xbdback_instance *xbdi; 832 struct xbdback_instance *xbdi;
833 833
834 SLIST_FOREACH(xbdi, &xbdback_instances, next) { 834 SLIST_FOREACH(xbdi, &xbdback_instances, next) {
835 if (xbdi->xbdi_domid == dom && xbdi->xbdi_handle == handle) 835 if (xbdi->xbdi_domid == dom && xbdi->xbdi_handle == handle)
836 return xbdi; 836 return xbdi;
837 } 837 }
838 return NULL; 838 return NULL;
839} 839}
840 840
841static int 841static int
842xbdback_evthandler(void *arg) 842xbdback_evthandler(void *arg)
843{ 843{
844 struct xbdback_instance *xbdi = arg; 844 struct xbdback_instance *xbdi = arg;
845 845
846 XENPRINTF(("xbdback_evthandler domain %d: cont %p\n", 846 XENPRINTF(("xbdback_evthandler domain %d: cont %p\n",
847 xbdi->xbdi_domid, xbdi->xbdi_cont)); 847 xbdi->xbdi_domid, xbdi->xbdi_cont));
848 848
849 if (xbdi->xbdi_cont == NULL) { 849 if (xbdi->xbdi_cont == NULL) {
850 xbdi->xbdi_cont = xbdback_co_main; 850 xbdi->xbdi_cont = xbdback_co_main;
851 xbdback_trampoline(xbdi, xbdi); 851 xbdback_trampoline(xbdi, xbdi);
852 } 852 }
853 return 1; 853 return 1;
854} 854}
855 855
856static void * 856static void *
857xbdback_co_main(struct xbdback_instance *xbdi, void *obj) 857xbdback_co_main(struct xbdback_instance *xbdi, void *obj)
858{ 858{
859 (void)obj; 859 (void)obj;
860 xbdi->xbdi_req_prod = xbdi->xbdi_ring.ring_n.sring->req_prod; 860 xbdi->xbdi_req_prod = xbdi->xbdi_ring.ring_n.sring->req_prod;
861 xen_rmb(); /* ensure we see all requests up to req_prod */ 861 xen_rmb(); /* ensure we see all requests up to req_prod */
862 /* 862 /*
863 * note that we'll eventually get a full ring of request. 863 * note that we'll eventually get a full ring of request.
864 * in this case, MASK_BLKIF_IDX(req_cons) == MASK_BLKIF_IDX(req_prod) 864 * in this case, MASK_BLKIF_IDX(req_cons) == MASK_BLKIF_IDX(req_prod)
865 */ 865 */
866 xbdi->xbdi_cont = xbdback_co_main_loop; 866 xbdi->xbdi_cont = xbdback_co_main_loop;
867 return xbdi; 867 return xbdi;
868} 868}
869 869
870static void * 870static void *
871xbdback_co_main_loop(struct xbdback_instance *xbdi, void *obj)  871xbdback_co_main_loop(struct xbdback_instance *xbdi, void *obj)
872{ 872{
873 blkif_request_t *req = &xbdi->xbdi_xen_req; 873 blkif_request_t *req = &xbdi->xbdi_xen_req;
874 blkif_x86_32_request_t *req32; 874 blkif_x86_32_request_t *req32;
875 blkif_x86_64_request_t *req64; 875 blkif_x86_64_request_t *req64;
876 876
877 (void)obj; 877 (void)obj;
878 if (xbdi->xbdi_ring.ring_n.req_cons != xbdi->xbdi_req_prod) { 878 if (xbdi->xbdi_ring.ring_n.req_cons != xbdi->xbdi_req_prod) {
879 switch(xbdi->xbdi_proto) { 879 switch(xbdi->xbdi_proto) {
880 case XBDIP_NATIVE: 880 case XBDIP_NATIVE:
881 memcpy(req, RING_GET_REQUEST(&xbdi->xbdi_ring.ring_n, 881 memcpy(req, RING_GET_REQUEST(&xbdi->xbdi_ring.ring_n,
882 xbdi->xbdi_ring.ring_n.req_cons), 882 xbdi->xbdi_ring.ring_n.req_cons),
883 sizeof(blkif_request_t)); 883 sizeof(blkif_request_t));
884 break; 884 break;
885 case XBDIP_32: 885 case XBDIP_32:
886 req32 = RING_GET_REQUEST(&xbdi->xbdi_ring.ring_32, 886 req32 = RING_GET_REQUEST(&xbdi->xbdi_ring.ring_32,
887 xbdi->xbdi_ring.ring_n.req_cons); 887 xbdi->xbdi_ring.ring_n.req_cons);
888 req->operation = req32->operation; 888 req->operation = req32->operation;
889 req->nr_segments = req32->nr_segments; 889 req->nr_segments = req32->nr_segments;
890 req->handle = req32->handle; 890 req->handle = req32->handle;
891 req->id = req32->id; 891 req->id = req32->id;
892 req->sector_number = req32->sector_number; 892 req->sector_number = req32->sector_number;
893 break; 893 break;
894  894
895 case XBDIP_64: 895 case XBDIP_64:
896 req64 = RING_GET_REQUEST(&xbdi->xbdi_ring.ring_64, 896 req64 = RING_GET_REQUEST(&xbdi->xbdi_ring.ring_64,
897 xbdi->xbdi_ring.ring_n.req_cons); 897 xbdi->xbdi_ring.ring_n.req_cons);
898 req->operation = req64->operation; 898 req->operation = req64->operation;
899 req->nr_segments = req64->nr_segments; 899 req->nr_segments = req64->nr_segments;
900 req->handle = req64->handle; 900 req->handle = req64->handle;
901 req->id = req64->id; 901 req->id = req64->id;
902 req->sector_number = req64->sector_number; 902 req->sector_number = req64->sector_number;
903 break; 903 break;
904 } 904 }
905 XENPRINTF(("xbdback op %d req_cons 0x%x req_prod 0x%x " 905 XENPRINTF(("xbdback op %d req_cons 0x%x req_prod 0x%x "
906 "resp_prod 0x%x id %" PRIu64 "\n", req->operation, 906 "resp_prod 0x%x id %" PRIu64 "\n", req->operation,
907 xbdi->xbdi_ring.ring_n.req_cons, 907 xbdi->xbdi_ring.ring_n.req_cons,
908 xbdi->xbdi_req_prod, 908 xbdi->xbdi_req_prod,
909 xbdi->xbdi_ring.ring_n.rsp_prod_pvt, 909 xbdi->xbdi_ring.ring_n.rsp_prod_pvt,
910 req->id)); 910 req->id));
911 switch(req->operation) { 911 switch(req->operation) {
912 case BLKIF_OP_READ: 912 case BLKIF_OP_READ:
913 case BLKIF_OP_WRITE: 913 case BLKIF_OP_WRITE:
914 xbdi->xbdi_cont = xbdback_co_io; 914 xbdi->xbdi_cont = xbdback_co_io;
915 break; 915 break;
916 case BLKIF_OP_FLUSH_DISKCACHE: 916 case BLKIF_OP_FLUSH_DISKCACHE:
917 xbdi_get(xbdi); 917 xbdi_get(xbdi);
918 xbdi->xbdi_cont = xbdback_co_cache_flush; 918 xbdi->xbdi_cont = xbdback_co_cache_flush;
919 break; 919 break;
920 default: 920 default:
921 printf("xbdback_evthandler domain %d: unknown " 921 printf("xbdback_evthandler domain %d: unknown "
922 "operation %d\n", xbdi->xbdi_domid, req->operation); 922 "operation %d\n", xbdi->xbdi_domid, req->operation);
923 xbdback_send_reply(xbdi, req->id, req->operation, 923 xbdback_send_reply(xbdi, req->id, req->operation,
924 BLKIF_RSP_ERROR); 924 BLKIF_RSP_ERROR);
925 xbdi->xbdi_cont = xbdback_co_main_incr; 925 xbdi->xbdi_cont = xbdback_co_main_incr;
926 break; 926 break;
927 } 927 }
928 } else { 928 } else {
929 xbdi->xbdi_cont = xbdback_co_main_done; 929 xbdi->xbdi_cont = xbdback_co_main_done;
930 } 930 }
931 return xbdi; 931 return xbdi;
932} 932}
933 933
934static void * 934static void *
935xbdback_co_main_incr(struct xbdback_instance *xbdi, void *obj) 935xbdback_co_main_incr(struct xbdback_instance *xbdi, void *obj)
936{ 936{
937 (void)obj; 937 (void)obj;
938 xbdi->xbdi_ring.ring_n.req_cons++; 938 xbdi->xbdi_ring.ring_n.req_cons++;
939 xbdi->xbdi_cont = xbdback_co_main_loop; 939 xbdi->xbdi_cont = xbdback_co_main_loop;
940 return xbdi; 940 return xbdi;
941} 941}
942 942
943static void * 943static void *
944xbdback_co_main_done(struct xbdback_instance *xbdi, void *obj) 944xbdback_co_main_done(struct xbdback_instance *xbdi, void *obj)
945{ 945{
946 (void)obj; 946 (void)obj;
947 if (xbdi->xbdi_io != NULL) { 947 if (xbdi->xbdi_io != NULL) {
948 xbdi->xbdi_cont = xbdback_co_flush; 948 xbdi->xbdi_cont = xbdback_co_flush;
949 xbdi->xbdi_cont_aux = xbdback_co_main_done2; 949 xbdi->xbdi_cont_aux = xbdback_co_main_done2;
950 } else { 950 } else {
951 xbdi->xbdi_cont = xbdback_co_main_done2; 951 xbdi->xbdi_cont = xbdback_co_main_done2;
952 } 952 }
953 return xbdi; 953 return xbdi;
954} 954}
955 955
956static void * 956static void *
957xbdback_co_main_done2(struct xbdback_instance *xbdi, void *obj) 957xbdback_co_main_done2(struct xbdback_instance *xbdi, void *obj)
958{ 958{
959 int work_to_do; 959 int work_to_do;
960 960
961 RING_FINAL_CHECK_FOR_REQUESTS(&xbdi->xbdi_ring.ring_n, work_to_do); 961 RING_FINAL_CHECK_FOR_REQUESTS(&xbdi->xbdi_ring.ring_n, work_to_do);
962 if (work_to_do) 962 if (work_to_do)
963 xbdi->xbdi_cont = xbdback_co_main; 963 xbdi->xbdi_cont = xbdback_co_main;
964 else 964 else
965 xbdi->xbdi_cont = NULL; 965 xbdi->xbdi_cont = NULL;
966 return xbdi; 966 return xbdi;
967} 967}
968 968
969static void * 969static void *
970xbdback_co_cache_flush(struct xbdback_instance *xbdi, void *obj) 970xbdback_co_cache_flush(struct xbdback_instance *xbdi, void *obj)
971{ 971{
972 (void)obj; 972 (void)obj;
973 XENPRINTF(("xbdback_co_cache_flush %p %p\n", xbdi, obj)); 973 XENPRINTF(("xbdback_co_cache_flush %p %p\n", xbdi, obj));
974 if (xbdi->xbdi_io != NULL) { 974 if (xbdi->xbdi_io != NULL) {
975 xbdi->xbdi_cont = xbdback_co_flush; 975 xbdi->xbdi_cont = xbdback_co_flush;
976 xbdi->xbdi_cont_aux = xbdback_co_cache_flush2; 976 xbdi->xbdi_cont_aux = xbdback_co_cache_flush2;
977 } else { 977 } else {
978 xbdi->xbdi_cont = xbdback_co_cache_flush2; 978 xbdi->xbdi_cont = xbdback_co_cache_flush2;
979 } 979 }
980 return xbdi; 980 return xbdi;
981} 981}
982 982
983static void * 983static void *
984xbdback_co_cache_flush2(struct xbdback_instance *xbdi, void *obj) 984xbdback_co_cache_flush2(struct xbdback_instance *xbdi, void *obj)
985{ 985{
986 (void)obj; 986 (void)obj;
987 XENPRINTF(("xbdback_co_cache_flush2 %p %p\n", xbdi, obj)); 987 XENPRINTF(("xbdback_co_cache_flush2 %p %p\n", xbdi, obj));
988 if (xbdi->xbdi_pendingreqs > 0) { 988 if (xbdi->xbdi_pendingreqs > 0) {
989 /* event or iodone will restart processing */ 989 /* event or iodone will restart processing */
990 xbdi->xbdi_cont = NULL; 990 xbdi->xbdi_cont = NULL;
991 xbdi_put(xbdi); 991 xbdi_put(xbdi);
992 return NULL; 992 return NULL;
993 } 993 }
994 xbdi->xbdi_cont = xbdback_co_cache_doflush; 994 xbdi->xbdi_cont = xbdback_co_cache_doflush;
995 return xbdback_pool_get(&xbdback_io_pool, xbdi); 995 return xbdback_pool_get(&xbdback_io_pool, xbdi);
996} 996}
997 997
998static void * 998static void *
999xbdback_co_cache_doflush(struct xbdback_instance *xbdi, void *obj) 999xbdback_co_cache_doflush(struct xbdback_instance *xbdi, void *obj)
1000{ 1000{
1001 struct xbdback_io *xbd_io; 1001 struct xbdback_io *xbd_io;
1002 1002
1003 XENPRINTF(("xbdback_co_cache_doflush %p %p\n", xbdi, obj)); 1003 XENPRINTF(("xbdback_co_cache_doflush %p %p\n", xbdi, obj));
1004 xbd_io = xbdi->xbdi_io = obj; 1004 xbd_io = xbdi->xbdi_io = obj;
1005 xbd_io->xio_xbdi = xbdi; 1005 xbd_io->xio_xbdi = xbdi;
1006 xbd_io->xio_operation = xbdi->xbdi_xen_req.operation; 1006 xbd_io->xio_operation = xbdi->xbdi_xen_req.operation;
1007 xbd_io->xio_flush_id = xbdi->xbdi_xen_req.id; 1007 xbd_io->xio_flush_id = xbdi->xbdi_xen_req.id;
1008 workqueue_enqueue(xbdback_workqueue, &xbdi->xbdi_io->xio_work, NULL); 1008 workqueue_enqueue(xbdback_workqueue, &xbdi->xbdi_io->xio_work, NULL);
1009 /* xbdback_do_io() will advance req pointer and restart processing */ 1009 /* xbdback_do_io() will advance req pointer and restart processing */
1010 xbdi->xbdi_cont = xbdback_co_cache_doflush; 1010 xbdi->xbdi_cont = xbdback_co_cache_doflush;
1011 return NULL; 1011 return NULL;
1012} 1012}
1013 1013
1014static void * 1014static void *
1015xbdback_co_io(struct xbdback_instance *xbdi, void *obj) 1015xbdback_co_io(struct xbdback_instance *xbdi, void *obj)
1016{  1016{
1017 int i, error; 1017 int i, error;
1018 blkif_request_t *req; 1018 blkif_request_t *req;
1019 blkif_x86_32_request_t *req32; 1019 blkif_x86_32_request_t *req32;
1020 blkif_x86_64_request_t *req64; 1020 blkif_x86_64_request_t *req64;
1021 1021
1022 (void)obj; 1022 (void)obj;
1023 1023
1024 /* some sanity checks */ 1024 /* some sanity checks */
1025 req = &xbdi->xbdi_xen_req; 1025 req = &xbdi->xbdi_xen_req;
1026 if (req->nr_segments < 1 || 1026 if (req->nr_segments < 1 ||
1027 req->nr_segments > BLKIF_MAX_SEGMENTS_PER_REQUEST) { 1027 req->nr_segments > BLKIF_MAX_SEGMENTS_PER_REQUEST) {
1028 printf("xbdback_io domain %d: %d segments\n", 1028 printf("xbdback_io domain %d: %d segments\n",
1029 xbdi->xbdi_domid, xbdi->xbdi_xen_req.nr_segments); 1029 xbdi->xbdi_domid, xbdi->xbdi_xen_req.nr_segments);
1030 error = EINVAL; 1030 error = EINVAL;
1031 goto end; 1031 goto end;
1032 } 1032 }
1033 1033
1034 if (req->operation == BLKIF_OP_WRITE) { 1034 if (req->operation == BLKIF_OP_WRITE) {
1035 if (xbdi->xbdi_ro) { 1035 if (xbdi->xbdi_ro) {
1036 error = EROFS; 1036 error = EROFS;
1037 goto end; 1037 goto end;
1038 } 1038 }
1039 } 1039 }
1040 1040
1041 xbdi->xbdi_segno = 0; 1041 xbdi->xbdi_segno = 0;
1042 1042
1043 /* copy request segments */ 1043 /* copy request segments */
1044 switch(xbdi->xbdi_proto) { 1044 switch(xbdi->xbdi_proto) {
1045 case XBDIP_NATIVE: 1045 case XBDIP_NATIVE:
1046 /* already copied in xbdback_co_main_loop */ 1046 /* already copied in xbdback_co_main_loop */
1047 break; 1047 break;
1048 case XBDIP_32: 1048 case XBDIP_32:
1049 req32 = RING_GET_REQUEST(&xbdi->xbdi_ring.ring_32, 1049 req32 = RING_GET_REQUEST(&xbdi->xbdi_ring.ring_32,
1050 xbdi->xbdi_ring.ring_n.req_cons); 1050 xbdi->xbdi_ring.ring_n.req_cons);
1051 for (i = 0; i < req->nr_segments; i++) 1051 for (i = 0; i < req->nr_segments; i++)
1052 req->seg[i] = req32->seg[i]; 1052 req->seg[i] = req32->seg[i];
1053 break; 1053 break;
1054 case XBDIP_64: 1054 case XBDIP_64:
1055 req64 = RING_GET_REQUEST(&xbdi->xbdi_ring.ring_64, 1055 req64 = RING_GET_REQUEST(&xbdi->xbdi_ring.ring_64,
1056 xbdi->xbdi_ring.ring_n.req_cons); 1056 xbdi->xbdi_ring.ring_n.req_cons);
1057 for (i = 0; i < req->nr_segments; i++) 1057 for (i = 0; i < req->nr_segments; i++)
1058 req->seg[i] = req64->seg[i]; 1058 req->seg[i] = req64->seg[i];
1059 break; 1059 break;
1060 } 1060 }
1061 1061
1062 xbdi->xbdi_cont = xbdback_co_io_gotreq; 1062 xbdi->xbdi_cont = xbdback_co_io_gotreq;
1063 return xbdback_pool_get(&xbdback_request_pool, xbdi); 1063 return xbdback_pool_get(&xbdback_request_pool, xbdi);
1064 end: 1064 end:
1065 xbdback_send_reply(xbdi, xbdi->xbdi_xen_req.id, 1065 xbdback_send_reply(xbdi, xbdi->xbdi_xen_req.id,
1066 xbdi->xbdi_xen_req.operation, error); 1066 xbdi->xbdi_xen_req.operation, error);
1067 xbdi->xbdi_cont = xbdback_co_main_incr; 1067 xbdi->xbdi_cont = xbdback_co_main_incr;
1068 return xbdi; 1068 return xbdi;
1069} 1069}
1070 1070
1071static void * 1071static void *
1072xbdback_co_io_gotreq(struct xbdback_instance *xbdi, void *obj) 1072xbdback_co_io_gotreq(struct xbdback_instance *xbdi, void *obj)
1073{ 1073{
1074 struct xbdback_request *xrq; 1074 struct xbdback_request *xrq;
1075 1075
1076 xrq = xbdi->xbdi_req = obj; 1076 xrq = xbdi->xbdi_req = obj;
1077  1077
1078 xrq->rq_xbdi = xbdi; 1078 xrq->rq_xbdi = xbdi;
1079 xrq->rq_iocount = 0; 1079 xrq->rq_iocount = 0;
1080 xrq->rq_ioerrs = 0; 1080 xrq->rq_ioerrs = 0;
1081 xrq->rq_id = xbdi->xbdi_xen_req.id; 1081 xrq->rq_id = xbdi->xbdi_xen_req.id;
1082 xrq->rq_operation = xbdi->xbdi_xen_req.operation; 1082 xrq->rq_operation = xbdi->xbdi_xen_req.operation;
1083 1083
1084 /*  1084 /*
1085 * Request-level reasons not to coalesce: different device, 1085 * Request-level reasons not to coalesce: different device,
1086 * different op, or noncontiguous disk sectors (vs. previous 1086 * different op, or noncontiguous disk sectors (vs. previous
1087 * request handed to us). 1087 * request handed to us).
1088 */ 1088 */
1089 xbdi->xbdi_cont = xbdback_co_io_loop; 1089 xbdi->xbdi_cont = xbdback_co_io_loop;
1090 if (xbdi->xbdi_io != NULL) { 1090 if (xbdi->xbdi_io != NULL) {
1091 struct xbdback_request *last_req; 1091 struct xbdback_request *last_req;
1092 last_req = SLIST_FIRST(&xbdi->xbdi_io->xio_rq)->car; 1092 last_req = SLIST_FIRST(&xbdi->xbdi_io->xio_rq)->car;
1093 XENPRINTF(("xbdback_io domain %d: hoping for sector %" PRIu64 1093 XENPRINTF(("xbdback_io domain %d: hoping for sector %" PRIu64
1094 "; got %" PRIu64 "\n", xbdi->xbdi_domid, 1094 "; got %" PRIu64 "\n", xbdi->xbdi_domid,
1095 xbdi->xbdi_next_sector, 1095 xbdi->xbdi_next_sector,
1096 xbdi->xbdi_xen_req.sector_number)); 1096 xbdi->xbdi_xen_req.sector_number));
1097 if ((xrq->rq_operation != last_req->rq_operation) 1097 if ((xrq->rq_operation != last_req->rq_operation)
1098 || (xbdi->xbdi_xen_req.sector_number != 1098 || (xbdi->xbdi_xen_req.sector_number !=
1099 xbdi->xbdi_next_sector)) { 1099 xbdi->xbdi_next_sector)) {
1100 XENPRINTF(("xbdback_io domain %d: segment break\n", 1100 XENPRINTF(("xbdback_io domain %d: segment break\n",
1101 xbdi->xbdi_domid)); 1101 xbdi->xbdi_domid));
1102 xbdi->xbdi_next_sector = 1102 xbdi->xbdi_next_sector =
1103 xbdi->xbdi_xen_req.sector_number; 1103 xbdi->xbdi_xen_req.sector_number;
1104 xbdi->xbdi_cont_aux = xbdi->xbdi_cont;  1104 xbdi->xbdi_cont_aux = xbdi->xbdi_cont;
1105 xbdi->xbdi_cont = xbdback_co_flush; 1105 xbdi->xbdi_cont = xbdback_co_flush;
1106 } 1106 }
1107 } else { 1107 } else {
1108 xbdi->xbdi_next_sector = xbdi->xbdi_xen_req.sector_number; 1108 xbdi->xbdi_next_sector = xbdi->xbdi_xen_req.sector_number;
1109 } 1109 }
1110 return xbdi; 1110 return xbdi;
1111} 1111}
1112 1112
1113 1113
1114static void * 1114static void *
1115xbdback_co_io_loop(struct xbdback_instance *xbdi, void *obj) 1115xbdback_co_io_loop(struct xbdback_instance *xbdi, void *obj)
1116{ 1116{
1117 struct xbdback_io *xio; 1117 struct xbdback_io *xio;
1118 1118
1119 (void)obj; 1119 (void)obj;
1120 if (xbdi->xbdi_segno < xbdi->xbdi_xen_req.nr_segments) { 1120 if (xbdi->xbdi_segno < xbdi->xbdi_xen_req.nr_segments) {
1121 uint8_t this_fs, this_ls, last_fs, last_ls; 1121 uint8_t this_fs, this_ls, last_fs, last_ls;
1122 grant_ref_t thisgrt, lastgrt; 1122 grant_ref_t thisgrt, lastgrt;
1123 /*  1123 /*
1124 * Segment-level reason to coalesce: handling full 1124 * Segment-level reason to coalesce: handling full
1125 * pages, or adjacent sector ranges from the same page 1125 * pages, or adjacent sector ranges from the same page
1126 * (and yes, this latter does happen). But not if the 1126 * (and yes, this latter does happen). But not if the
1127 * array of client pseudo-physical pages is full. 1127 * array of client pseudo-physical pages is full.
1128 */ 1128 */
1129 this_fs = xbdi->xbdi_xen_req.seg[xbdi->xbdi_segno].first_sect; 1129 this_fs = xbdi->xbdi_xen_req.seg[xbdi->xbdi_segno].first_sect;
1130 this_ls = xbdi->xbdi_xen_req.seg[xbdi->xbdi_segno].last_sect; 1130 this_ls = xbdi->xbdi_xen_req.seg[xbdi->xbdi_segno].last_sect;
1131 thisgrt = xbdi->xbdi_xen_req.seg[xbdi->xbdi_segno].gref; 1131 thisgrt = xbdi->xbdi_xen_req.seg[xbdi->xbdi_segno].gref;
1132 XENPRINTF(("xbdback_io domain %d: " 1132 XENPRINTF(("xbdback_io domain %d: "
1133 "first,last_sect[%d]=0%o,0%o\n", 1133 "first,last_sect[%d]=0%o,0%o\n",
1134 xbdi->xbdi_domid, xbdi->xbdi_segno, 1134 xbdi->xbdi_domid, xbdi->xbdi_segno,
1135 this_fs, this_ls)); 1135 this_fs, this_ls));
1136 last_fs = xbdi->xbdi_last_fs = xbdi->xbdi_this_fs; 1136 last_fs = xbdi->xbdi_last_fs = xbdi->xbdi_this_fs;
1137 last_ls = xbdi->xbdi_last_ls = xbdi->xbdi_this_ls; 1137 last_ls = xbdi->xbdi_last_ls = xbdi->xbdi_this_ls;
1138 lastgrt = xbdi->xbdi_lastgrt = xbdi->xbdi_thisgrt; 1138 lastgrt = xbdi->xbdi_lastgrt = xbdi->xbdi_thisgrt;
1139 xbdi->xbdi_this_fs = this_fs; 1139 xbdi->xbdi_this_fs = this_fs;
1140 xbdi->xbdi_this_ls = this_ls; 1140 xbdi->xbdi_this_ls = this_ls;
1141 xbdi->xbdi_thisgrt = thisgrt; 1141 xbdi->xbdi_thisgrt = thisgrt;
1142 if (xbdi->xbdi_io != NULL) { 1142 if (xbdi->xbdi_io != NULL) {
1143 if (last_ls == VBD_MAXSECT 1143 if (last_ls == VBD_MAXSECT
1144 && this_fs == 0 1144 && this_fs == 0
1145 && xbdi->xbdi_io->xio_nrma 1145 && xbdi->xbdi_io->xio_nrma
1146 < XENSHM_MAX_PAGES_PER_REQUEST) { 1146 < XENSHM_MAX_PAGES_PER_REQUEST) {
1147 xbdi->xbdi_same_page = 0; 1147 xbdi->xbdi_same_page = 0;
1148 } else if (last_ls + 1 1148 } else if (last_ls + 1
1149 == this_fs 1149 == this_fs
1150#ifdef notyet 1150#ifdef notyet
1151 && (last_fas & ~PAGE_MASK) 1151 && (last_fas & ~PAGE_MASK)
1152 == (this_fas & ~PAGE_MASK) 1152 == (this_fas & ~PAGE_MASK)
1153#else  1153#else
1154 && 0 /* can't know frame number yet */ 1154 && 0 /* can't know frame number yet */
1155#endif 1155#endif
1156 ) { 1156 ) {
1157#ifdef DEBUG 1157#ifdef DEBUG
1158 static struct timeval gluetimer; 1158 static struct timeval gluetimer;
1159 if (ratecheck(&gluetimer, 1159 if (ratecheck(&gluetimer,
1160 &xbdback_fragio_intvl)) 1160 &xbdback_fragio_intvl))
1161 printf("xbdback: domain %d sending" 1161 printf("xbdback: domain %d sending"
1162 " excessively fragmented I/O\n", 1162 " excessively fragmented I/O\n",
1163 xbdi->xbdi_domid); 1163 xbdi->xbdi_domid);
1164#endif 1164#endif
1165 printf("xbdback_io: would maybe glue same page sec %d (%d->%d)\n", xbdi->xbdi_segno, this_fs, this_ls); 1165 printf("xbdback_io: would maybe glue same page sec %d (%d->%d)\n", xbdi->xbdi_segno, this_fs, this_ls);
1166 panic("notyet!"); 1166 panic("notyet!");
1167 XENPRINTF(("xbdback_io domain %d: glue same " 1167 XENPRINTF(("xbdback_io domain %d: glue same "
1168 "page", xbdi->xbdi_domid)); 1168 "page", xbdi->xbdi_domid));
1169 xbdi->xbdi_same_page = 1; 1169 xbdi->xbdi_same_page = 1;
1170 } else { 1170 } else {
1171 xbdi->xbdi_cont_aux = xbdback_co_io_loop; 1171 xbdi->xbdi_cont_aux = xbdback_co_io_loop;
1172 xbdi->xbdi_cont = xbdback_co_flush; 1172 xbdi->xbdi_cont = xbdback_co_flush;
1173 return xbdi; 1173 return xbdi;
1174 } 1174 }
1175 } else 1175 } else
1176 xbdi->xbdi_same_page = 0; 1176 xbdi->xbdi_same_page = 0;
1177 1177
1178 if (xbdi->xbdi_io == NULL) { 1178 if (xbdi->xbdi_io == NULL) {
1179 xbdi->xbdi_cont = xbdback_co_io_gotio; 1179 xbdi->xbdi_cont = xbdback_co_io_gotio;
1180 xio = xbdback_pool_get(&xbdback_io_pool, xbdi); 1180 xio = xbdback_pool_get(&xbdback_io_pool, xbdi);
1181 return xio; 1181 return xio;
1182 } else { 1182 } else {
1183 xbdi->xbdi_cont = xbdback_co_io_gotio2; 1183 xbdi->xbdi_cont = xbdback_co_io_gotio2;
1184 } 1184 }
1185 } else { 1185 } else {
1186 /* done with the loop over segments; get next request */ 1186 /* done with the loop over segments; get next request */
1187 xbdi->xbdi_cont = xbdback_co_main_incr; 1187 xbdi->xbdi_cont = xbdback_co_main_incr;
1188 } 1188 }
1189 return xbdi;  1189 return xbdi;
1190} 1190}
1191 1191
1192 1192
1193static void * 1193static void *
1194xbdback_co_io_gotio(struct xbdback_instance *xbdi, void *obj) 1194xbdback_co_io_gotio(struct xbdback_instance *xbdi, void *obj)
1195 1195
1196{ 1196{
1197 struct xbdback_io *xbd_io; 1197 struct xbdback_io *xbd_io;
1198 vaddr_t start_offset; /* start offset in vm area */ 1198 vaddr_t start_offset; /* start offset in vm area */
1199 int buf_flags; 1199 int buf_flags;
1200 1200
1201 xbdi_get(xbdi); 1201 xbdi_get(xbdi);
1202 atomic_inc_uint(&xbdi->xbdi_pendingreqs); 1202 atomic_inc_uint(&xbdi->xbdi_pendingreqs);
1203  1203
1204 xbd_io = xbdi->xbdi_io = obj; 1204 xbd_io = xbdi->xbdi_io = obj;
1205 buf_init(&xbd_io->xio_buf); 1205 buf_init(&xbd_io->xio_buf);
1206 xbd_io->xio_xbdi = xbdi; 1206 xbd_io->xio_xbdi = xbdi;
1207 SLIST_INIT(&xbd_io->xio_rq); 1207 SLIST_INIT(&xbd_io->xio_rq);
1208 xbd_io->xio_nrma = 0; 1208 xbd_io->xio_nrma = 0;
1209 xbd_io->xio_mapped = 0; 1209 xbd_io->xio_mapped = 0;
1210 xbd_io->xio_operation = xbdi->xbdi_xen_req.operation; 1210 xbd_io->xio_operation = xbdi->xbdi_xen_req.operation;
1211 1211
1212 start_offset = xbdi->xbdi_this_fs * VBD_BSIZE; 1212 start_offset = xbdi->xbdi_this_fs * VBD_BSIZE;
1213  1213
1214 if (xbdi->xbdi_xen_req.operation == BLKIF_OP_WRITE) { 1214 if (xbdi->xbdi_xen_req.operation == BLKIF_OP_WRITE) {
1215 buf_flags = B_WRITE; 1215 buf_flags = B_WRITE;
1216 } else { 1216 } else {
1217 buf_flags = B_READ; 1217 buf_flags = B_READ;
1218 } 1218 }
1219 1219
1220 xbd_io->xio_buf.b_flags = buf_flags; 1220 xbd_io->xio_buf.b_flags = buf_flags;
1221 xbd_io->xio_buf.b_cflags = 0; 1221 xbd_io->xio_buf.b_cflags = 0;
1222 xbd_io->xio_buf.b_oflags = 0; 1222 xbd_io->xio_buf.b_oflags = 0;
1223 xbd_io->xio_buf.b_iodone = xbdback_iodone; 1223 xbd_io->xio_buf.b_iodone = xbdback_iodone;
1224 xbd_io->xio_buf.b_proc = NULL; 1224 xbd_io->xio_buf.b_proc = NULL;
1225 xbd_io->xio_buf.b_vp = xbdi->xbdi_vp; 1225 xbd_io->xio_buf.b_vp = xbdi->xbdi_vp;
1226 xbd_io->xio_buf.b_objlock = &xbdi->xbdi_vp->v_interlock; 1226 xbd_io->xio_buf.b_objlock = &xbdi->xbdi_vp->v_interlock;
1227 xbd_io->xio_buf.b_dev = xbdi->xbdi_dev; 1227 xbd_io->xio_buf.b_dev = xbdi->xbdi_dev;
1228 xbd_io->xio_buf.b_blkno = xbdi->xbdi_next_sector; 1228 xbd_io->xio_buf.b_blkno = xbdi->xbdi_next_sector;
1229 xbd_io->xio_buf.b_bcount = 0; 1229 xbd_io->xio_buf.b_bcount = 0;
1230 xbd_io->xio_buf.b_data = (void *)start_offset; 1230 xbd_io->xio_buf.b_data = (void *)start_offset;
1231 xbd_io->xio_buf.b_private = xbd_io; 1231 xbd_io->xio_buf.b_private = xbd_io;
1232 1232
1233 xbdi->xbdi_cont = xbdback_co_io_gotio2; 1233 xbdi->xbdi_cont = xbdback_co_io_gotio2;
1234 return xbdi; 1234 return xbdi;
1235} 1235}
1236 1236
1237 1237
1238static void * 1238static void *
1239xbdback_co_io_gotio2(struct xbdback_instance *xbdi, void *obj) 1239xbdback_co_io_gotio2(struct xbdback_instance *xbdi, void *obj)
1240{ 1240{
1241 (void)obj; 1241 (void)obj;
1242 if (xbdi->xbdi_segno == 0 || SLIST_EMPTY(&xbdi->xbdi_io->xio_rq)) { 1242 if (xbdi->xbdi_segno == 0 || SLIST_EMPTY(&xbdi->xbdi_io->xio_rq)) {
1243 /* if this is the first segment of a new request */ 1243 /* if this is the first segment of a new request */
1244 /* or if it's the first segment of the io */ 1244 /* or if it's the first segment of the io */
1245 xbdi->xbdi_cont = xbdback_co_io_gotfrag; 1245 xbdi->xbdi_cont = xbdback_co_io_gotfrag;
1246 return xbdback_pool_get(&xbdback_fragment_pool, xbdi); 1246 return xbdback_pool_get(&xbdback_fragment_pool, xbdi);
1247 } 1247 }
1248 xbdi->xbdi_cont = xbdback_co_io_gotfrag2; 1248 xbdi->xbdi_cont = xbdback_co_io_gotfrag2;
1249 return xbdi; 1249 return xbdi;
1250} 1250}
1251 1251
1252 1252
1253static void * 1253static void *
1254xbdback_co_io_gotfrag(struct xbdback_instance *xbdi, void *obj) 1254xbdback_co_io_gotfrag(struct xbdback_instance *xbdi, void *obj)
1255{ 1255{
1256 struct xbdback_fragment *xbd_fr; 1256 struct xbdback_fragment *xbd_fr;
1257 1257
1258 xbd_fr = obj; 1258 xbd_fr = obj;
1259 xbd_fr->car = xbdi->xbdi_req; 1259 xbd_fr->car = xbdi->xbdi_req;
1260 SLIST_INSERT_HEAD(&xbdi->xbdi_io->xio_rq, xbd_fr, cdr); 1260 SLIST_INSERT_HEAD(&xbdi->xbdi_io->xio_rq, xbd_fr, cdr);
1261 ++xbdi->xbdi_req->rq_iocount; 1261 ++xbdi->xbdi_req->rq_iocount;
1262 1262
1263 xbdi->xbdi_cont = xbdback_co_io_gotfrag2; 1263 xbdi->xbdi_cont = xbdback_co_io_gotfrag2;
1264 return xbdi; 1264 return xbdi;
1265} 1265}
1266 1266
1267static void * 1267static void *
1268xbdback_co_io_gotfrag2(struct xbdback_instance *xbdi, void *obj) 1268xbdback_co_io_gotfrag2(struct xbdback_instance *xbdi, void *obj)
1269{ 1269{
1270 struct xbdback_io *xbd_io; 1270 struct xbdback_io *xbd_io;
1271 int seg_size; 1271 int seg_size;
1272 uint8_t this_fs, this_ls; 1272 uint8_t this_fs, this_ls;
1273 1273
1274 this_fs = xbdi->xbdi_this_fs; 1274 this_fs = xbdi->xbdi_this_fs;
1275 this_ls = xbdi->xbdi_this_ls; 1275 this_ls = xbdi->xbdi_this_ls;
1276 xbd_io = xbdi->xbdi_io; 1276 xbd_io = xbdi->xbdi_io;
1277 seg_size = this_ls - this_fs + 1; 1277 seg_size = this_ls - this_fs + 1;
1278 1278
1279 if (seg_size < 0) { 1279 if (seg_size < 0) {
1280 printf("xbdback_io domain %d: negative-size request (%d %d)\n", 1280 printf("xbdback_io domain %d: negative-size request (%d %d)\n",
1281 xbdi->xbdi_domid, this_ls, this_fs); 1281 xbdi->xbdi_domid, this_ls, this_fs);
1282 xbdback_io_error(xbdi->xbdi_io, EINVAL); 1282 xbdback_io_error(xbdi->xbdi_io, EINVAL);
1283 xbdi->xbdi_io = NULL; 1283 xbdi->xbdi_io = NULL;
1284 xbdi->xbdi_cont = xbdback_co_main_incr; 1284 xbdi->xbdi_cont = xbdback_co_main_incr;
1285 return xbdi; 1285 return xbdi;
1286 } 1286 }
1287  1287
1288 if (!xbdi->xbdi_same_page) { 1288 if (!xbdi->xbdi_same_page) {
1289 XENPRINTF(("xbdback_io domain %d: appending grant %u\n", 1289 XENPRINTF(("xbdback_io domain %d: appending grant %u\n",
1290 xbdi->xbdi_domid, (u_int)xbdi->xbdi_thisgrt)); 1290 xbdi->xbdi_domid, (u_int)xbdi->xbdi_thisgrt));
1291 xbd_io->xio_gref[xbd_io->xio_nrma++] = xbdi->xbdi_thisgrt; 1291 xbd_io->xio_gref[xbd_io->xio_nrma++] = xbdi->xbdi_thisgrt;
1292 } 1292 }
1293 1293
1294 xbd_io->xio_buf.b_bcount += (daddr_t)(seg_size * VBD_BSIZE); 1294 xbd_io->xio_buf.b_bcount += (daddr_t)(seg_size * VBD_BSIZE);
1295 XENPRINTF(("xbdback_io domain %d: start sect %d size %d\n", 1295 XENPRINTF(("xbdback_io domain %d: start sect %d size %d\n",
1296 xbdi->xbdi_domid, (int)xbdi->xbdi_next_sector, seg_size)); 1296 xbdi->xbdi_domid, (int)xbdi->xbdi_next_sector, seg_size));
1297  1297
1298 /* Finally, the end of the segment loop! */ 1298 /* Finally, the end of the segment loop! */
1299 xbdi->xbdi_next_sector += seg_size; 1299 xbdi->xbdi_next_sector += seg_size;
1300 ++xbdi->xbdi_segno; 1300 ++xbdi->xbdi_segno;
1301 xbdi->xbdi_cont = xbdback_co_io_loop; 1301 xbdi->xbdi_cont = xbdback_co_io_loop;
1302 return xbdi; 1302 return xbdi;
1303} 1303}
1304 1304
1305 1305
1306static void * 1306static void *
1307xbdback_co_flush(struct xbdback_instance *xbdi, void *obj) 1307xbdback_co_flush(struct xbdback_instance *xbdi, void *obj)
1308{ 1308{
1309 (void)obj; 1309 (void)obj;
1310 XENPRINTF(("xbdback_io domain %d: flush sect %ld size %d ptr 0x%lx\n", 1310 XENPRINTF(("xbdback_io domain %d: flush sect %ld size %d ptr 0x%lx\n",
1311 xbdi->xbdi_domid, (long)xbdi->xbdi_io->xio_buf.b_blkno, 1311 xbdi->xbdi_domid, (long)xbdi->xbdi_io->xio_buf.b_blkno,
1312 (int)xbdi->xbdi_io->xio_buf.b_bcount, (long)xbdi->xbdi_io)); 1312 (int)xbdi->xbdi_io->xio_buf.b_bcount, (long)xbdi->xbdi_io));
1313 xbdi->xbdi_cont = xbdback_co_flush_done; 1313 xbdi->xbdi_cont = xbdback_co_flush_done;
1314 return xbdback_map_shm(xbdi->xbdi_io); 1314 return xbdback_map_shm(xbdi->xbdi_io);
1315} 1315}
1316 1316
1317static void * 1317static void *
1318xbdback_co_flush_done(struct xbdback_instance *xbdi, void *obj) 1318xbdback_co_flush_done(struct xbdback_instance *xbdi, void *obj)
1319{ 1319{
1320 (void)obj; 1320 (void)obj;
1321 workqueue_enqueue(xbdback_workqueue, &xbdi->xbdi_io->xio_work, NULL); 1321 workqueue_enqueue(xbdback_workqueue, &xbdi->xbdi_io->xio_work, NULL);
1322 xbdi->xbdi_io = NULL; 1322 xbdi->xbdi_io = NULL;
1323 xbdi->xbdi_cont = xbdi->xbdi_cont_aux; 1323 xbdi->xbdi_cont = xbdi->xbdi_cont_aux;
1324 return xbdi; 1324 return xbdi;
1325} 1325}
1326 1326
1327static void 1327static void
1328xbdback_io_error(struct xbdback_io *xbd_io, int error) 1328xbdback_io_error(struct xbdback_io *xbd_io, int error)
1329{ 1329{
1330 xbd_io->xio_buf.b_error = error; 1330 xbd_io->xio_buf.b_error = error;
1331 xbdback_iodone(&xbd_io->xio_buf); 1331 xbdback_iodone(&xbd_io->xio_buf);
1332} 1332}
1333 1333
1334static void 1334static void
1335xbdback_do_io(struct work *wk, void *dummy) 1335xbdback_do_io(struct work *wk, void *dummy)
1336{ 1336{
1337 struct xbdback_io *xbd_io = (void *)wk; 1337 struct xbdback_io *xbd_io = (void *)wk;
1338 KASSERT(&xbd_io->xio_work == wk); 1338 KASSERT(&xbd_io->xio_work == wk);
1339 1339
1340 if (xbd_io->xio_operation == BLKIF_OP_FLUSH_DISKCACHE) { 1340 if (xbd_io->xio_operation == BLKIF_OP_FLUSH_DISKCACHE) {
1341 int error; 1341 int error;
1342 int force = 1; 1342 int force = 1;
1343 struct xbdback_instance *xbdi = xbd_io->xio_xbdi; 1343 struct xbdback_instance *xbdi = xbd_io->xio_xbdi;
1344 1344
1345 error = VOP_IOCTL(xbdi->xbdi_vp, DIOCCACHESYNC, &force, FWRITE, 1345 error = VOP_IOCTL(xbdi->xbdi_vp, DIOCCACHESYNC, &force, FWRITE,
1346 kauth_cred_get()); 1346 kauth_cred_get());
1347 if (error) { 1347 if (error) {
1348 aprint_error("xbdback %s: DIOCCACHESYNC returned %d\n", 1348 aprint_error("xbdback %s: DIOCCACHESYNC returned %d\n",
1349 xbdi->xbdi_xbusd->xbusd_path, error); 1349 xbdi->xbdi_xbusd->xbusd_path, error);
1350 if (error == EOPNOTSUPP || error == ENOTTY) 1350 if (error == EOPNOTSUPP || error == ENOTTY)
1351 error = BLKIF_RSP_EOPNOTSUPP; 1351 error = BLKIF_RSP_EOPNOTSUPP;
1352 else 1352 else
1353 error = BLKIF_RSP_ERROR; 1353 error = BLKIF_RSP_ERROR;
1354 } else 1354 } else
1355 error = BLKIF_RSP_OKAY; 1355 error = BLKIF_RSP_OKAY;
1356 xbdback_send_reply(xbdi, xbd_io->xio_flush_id, 1356 xbdback_send_reply(xbdi, xbd_io->xio_flush_id,
1357 xbd_io->xio_operation, error); 1357 xbd_io->xio_operation, error);
1358 xbdback_pool_put(&xbdback_io_pool, xbd_io); 1358 xbdback_pool_put(&xbdback_io_pool, xbd_io);
1359 xbdi_put(xbdi); 1359 xbdi_put(xbdi);
1360 /* handle next IO */ 1360 /* handle next IO */
1361 xbdi->xbdi_io = NULL; 1361 xbdi->xbdi_io = NULL;
1362 xbdi->xbdi_cont = xbdback_co_main_incr; 1362 xbdi->xbdi_cont = xbdback_co_main_incr;
1363 xbdback_trampoline(xbdi, xbdi); 1363 xbdback_trampoline(xbdi, xbdi);
1364 return; 1364 return;
1365 } 1365 }
1366 1366
1367 /* should be read or write */ 1367 /* should be read or write */
1368 xbd_io->xio_buf.b_data = 1368 xbd_io->xio_buf.b_data =
1369 (void *)((vaddr_t)xbd_io->xio_buf.b_data + xbd_io->xio_vaddr); 1369 (void *)((vaddr_t)xbd_io->xio_buf.b_data + xbd_io->xio_vaddr);
1370#ifdef DIAGNOSTIC 1370#ifdef DIAGNOSTIC
1371 { 1371 {
1372 vaddr_t bdata = (vaddr_t)xbd_io->xio_buf.b_data; 1372 vaddr_t bdata = (vaddr_t)xbd_io->xio_buf.b_data;
1373 int nsegs = 1373 int nsegs =
1374 ((((bdata + xbd_io->xio_buf.b_bcount - 1) & ~PAGE_MASK) - 1374 ((((bdata + xbd_io->xio_buf.b_bcount - 1) & ~PAGE_MASK) -
1375 (bdata & ~PAGE_MASK)) >> PAGE_SHIFT) + 1; 1375 (bdata & ~PAGE_MASK)) >> PAGE_SHIFT) + 1;
1376 if ((bdata & ~PAGE_MASK) != (xbd_io->xio_vaddr & ~PAGE_MASK)) { 1376 if ((bdata & ~PAGE_MASK) != (xbd_io->xio_vaddr & ~PAGE_MASK)) {
1377 printf("xbdback_do_io vaddr 0x%lx bdata 0x%lx\n", 1377 printf("xbdback_do_io vaddr 0x%lx bdata 0x%lx\n",
1378 xbd_io->xio_vaddr, bdata); 1378 xbd_io->xio_vaddr, bdata);
1379 panic("xbdback_do_io: bdata page change"); 1379 panic("xbdback_do_io: bdata page change");
1380 } 1380 }
1381 if (nsegs > xbd_io->xio_nrma) { 1381 if (nsegs > xbd_io->xio_nrma) {
1382 printf("xbdback_do_io vaddr 0x%lx bcount 0x%x doesn't fit in " 1382 printf("xbdback_do_io vaddr 0x%lx bcount 0x%x doesn't fit in "
1383 " %d pages\n", bdata, xbd_io->xio_buf.b_bcount, 1383 " %d pages\n", bdata, xbd_io->xio_buf.b_bcount,
1384 xbd_io->xio_nrma); 1384 xbd_io->xio_nrma);
1385 panic("xbdback_do_io: not enough pages"); 1385 panic("xbdback_do_io: not enough pages");
1386 } 1386 }
1387 } 1387 }
1388#endif 1388#endif
1389 if ((xbd_io->xio_buf.b_flags & B_READ) == 0) { 1389 if ((xbd_io->xio_buf.b_flags & B_READ) == 0) {
1390 mutex_enter(&xbd_io->xio_buf.b_vp->v_interlock); 1390 mutex_enter(&xbd_io->xio_buf.b_vp->v_interlock);
1391 xbd_io->xio_buf.b_vp->v_numoutput++; 1391 xbd_io->xio_buf.b_vp->v_numoutput++;
1392 mutex_exit(&xbd_io->xio_buf.b_vp->v_interlock); 1392 mutex_exit(&xbd_io->xio_buf.b_vp->v_interlock);
1393 } 1393 }
1394 bdev_strategy(&xbd_io->xio_buf); 1394 bdev_strategy(&xbd_io->xio_buf);
1395} 1395}
1396 1396
1397/* This gets reused by xbdback_io_error to report errors from other sources. */ 1397/* This gets reused by xbdback_io_error to report errors from other sources. */
1398static void 1398static void
1399xbdback_iodone(struct buf *bp) 1399xbdback_iodone(struct buf *bp)
1400{ 1400{
1401 struct xbdback_io *xbd_io; 1401 struct xbdback_io *xbd_io;
1402 struct xbdback_instance *xbdi; 1402 struct xbdback_instance *xbdi;
1403 int errp; 1403 int errp;
1404 int s; 1404 int s;
1405 1405
1406 xbd_io = bp->b_private; 1406 xbd_io = bp->b_private;
1407 xbdi = xbd_io->xio_xbdi; 1407 xbdi = xbd_io->xio_xbdi;
1408 1408
1409 XENPRINTF(("xbdback_io domain %d: iodone ptr 0x%lx\n", 1409 XENPRINTF(("xbdback_io domain %d: iodone ptr 0x%lx\n",
1410 xbdi->xbdi_domid, (long)xbd_io)); 1410 xbdi->xbdi_domid, (long)xbd_io));
1411 1411
1412 if (xbd_io->xio_mapped) 1412 if (xbd_io->xio_mapped)
1413 xbdback_unmap_shm(xbd_io); 1413 xbdback_unmap_shm(xbd_io);
1414 1414
1415 if (bp->b_error != 0) { 1415 if (bp->b_error != 0) {
1416 printf("xbd IO domain %d: error %d\n", 1416 printf("xbd IO domain %d: error %d\n",
1417 xbdi->xbdi_domid, bp->b_error); 1417 xbdi->xbdi_domid, bp->b_error);
1418 errp = 1; 1418 errp = 1;
1419 } else 1419 } else
1420 errp = 0; 1420 errp = 0;
1421 1421
1422  1422
1423 /* for each constituent xbd request */ 1423 /* for each constituent xbd request */
1424 while(!SLIST_EMPTY(&xbd_io->xio_rq)) { 1424 while(!SLIST_EMPTY(&xbd_io->xio_rq)) {
1425 struct xbdback_fragment *xbd_fr; 1425 struct xbdback_fragment *xbd_fr;
1426 struct xbdback_request *xbd_req; 1426 struct xbdback_request *xbd_req;
1427 struct xbdback_instance *rxbdi; 1427 struct xbdback_instance *rxbdi;
1428 int error; 1428 int error;
1429  1429
1430 xbd_fr = SLIST_FIRST(&xbd_io->xio_rq); 1430 xbd_fr = SLIST_FIRST(&xbd_io->xio_rq);
1431 xbd_req = xbd_fr->car; 1431 xbd_req = xbd_fr->car;
1432 SLIST_REMOVE_HEAD(&xbd_io->xio_rq, cdr); 1432 SLIST_REMOVE_HEAD(&xbd_io->xio_rq, cdr);
1433 xbdback_pool_put(&xbdback_fragment_pool, xbd_fr); 1433 xbdback_pool_put(&xbdback_fragment_pool, xbd_fr);
1434  1434
1435 if (errp) 1435 if (errp)
1436 ++xbd_req->rq_ioerrs; 1436 ++xbd_req->rq_ioerrs;
1437  1437
1438 /* finalize it only if this was its last I/O */ 1438 /* finalize it only if this was its last I/O */
1439 if (--xbd_req->rq_iocount > 0) 1439 if (--xbd_req->rq_iocount > 0)
1440 continue; 1440 continue;
1441 1441
1442 rxbdi = xbd_req->rq_xbdi; 1442 rxbdi = xbd_req->rq_xbdi;
1443 KASSERT(xbdi == rxbdi); 1443 KASSERT(xbdi == rxbdi);
1444  1444
1445 error = xbd_req->rq_ioerrs > 0 1445 error = xbd_req->rq_ioerrs > 0
1446 ? BLKIF_RSP_ERROR 1446 ? BLKIF_RSP_ERROR
1447 : BLKIF_RSP_OKAY; 1447 : BLKIF_RSP_OKAY;
1448 1448
1449 XENPRINTF(("xbdback_io domain %d: end request %" PRIu64 " error=%d\n", 1449 XENPRINTF(("xbdback_io domain %d: end request %" PRIu64 " error=%d\n",
1450 xbdi->xbdi_domid, xbd_req->rq_id, error)); 1450 xbdi->xbdi_domid, xbd_req->rq_id, error));
1451 xbdback_send_reply(xbdi, xbd_req->rq_id, 1451 xbdback_send_reply(xbdi, xbd_req->rq_id,
1452 xbd_req->rq_operation, error); 1452 xbd_req->rq_operation, error);
1453 xbdback_pool_put(&xbdback_request_pool, xbd_req); 1453 xbdback_pool_put(&xbdback_request_pool, xbd_req);
1454 } 1454 }
1455 xbdi_put(xbdi); 1455 xbdi_put(xbdi);
1456 atomic_dec_uint(&xbdi->xbdi_pendingreqs); 1456 atomic_dec_uint(&xbdi->xbdi_pendingreqs);
1457 buf_destroy(&xbd_io->xio_buf); 1457 buf_destroy(&xbd_io->xio_buf);
1458 xbdback_pool_put(&xbdback_io_pool, xbd_io); 1458 xbdback_pool_put(&xbdback_io_pool, xbd_io);
1459 s = splbio(); 1459 s = splbio();
1460 if (xbdi->xbdi_cont == NULL) { 1460 if (xbdi->xbdi_cont == NULL) {
1461 /* check if there is more work to do */ 1461 /* check if there is more work to do */
1462 xbdi->xbdi_cont = xbdback_co_main; 1462 xbdi->xbdi_cont = xbdback_co_main;
1463 xbdback_trampoline(xbdi, xbdi); 1463 xbdback_trampoline(xbdi, xbdi);
1464 } 1464 }
1465 splx(s); 1465 splx(s);
1466} 1466}
1467 1467
1468/* 1468/*
1469 * called once a request has completed. Place the reply in the ring and 1469 * called once a request has completed. Place the reply in the ring and
1470 * notify the guest OS 1470 * notify the guest OS
1471 */ 1471 */
1472static void 1472static void
1473xbdback_send_reply(struct xbdback_instance *xbdi, uint64_t id, 1473xbdback_send_reply(struct xbdback_instance *xbdi, uint64_t id,
1474 int op, int status) 1474 int op, int status)
1475{ 1475{
1476 blkif_response_t *resp_n; 1476 blkif_response_t *resp_n;
1477 blkif_x86_32_response_t *resp32; 1477 blkif_x86_32_response_t *resp32;
1478 blkif_x86_64_response_t *resp64; 1478 blkif_x86_64_response_t *resp64;
1479 int notify; 1479 int notify;
1480 1480
1481 switch(xbdi->xbdi_proto) { 1481 switch(xbdi->xbdi_proto) {
1482 case XBDIP_NATIVE: 1482 case XBDIP_NATIVE:
1483 resp_n = RING_GET_RESPONSE(&xbdi->xbdi_ring.ring_n, 1483 resp_n = RING_GET_RESPONSE(&xbdi->xbdi_ring.ring_n,
1484 xbdi->xbdi_ring.ring_n.rsp_prod_pvt); 1484 xbdi->xbdi_ring.ring_n.rsp_prod_pvt);
1485 resp_n->id = id; 1485 resp_n->id = id;
1486 resp_n->operation = op; 1486 resp_n->operation = op;
1487 resp_n->status = status; 1487 resp_n->status = status;
1488 break; 1488 break;
1489 case XBDIP_32: 1489 case XBDIP_32:
1490 resp32 = RING_GET_RESPONSE(&xbdi->xbdi_ring.ring_32, 1490 resp32 = RING_GET_RESPONSE(&xbdi->xbdi_ring.ring_32,
1491 xbdi->xbdi_ring.ring_n.rsp_prod_pvt); 1491 xbdi->xbdi_ring.ring_n.rsp_prod_pvt);
1492 resp32->id = id; 1492 resp32->id = id;
1493 resp32->operation = op; 1493 resp32->operation = op;
1494 resp32->status = status; 1494 resp32->status = status;
1495 break; 1495 break;
1496 case XBDIP_64: 1496 case XBDIP_64:
1497 resp64 = RING_GET_RESPONSE(&xbdi->xbdi_ring.ring_64, 1497 resp64 = RING_GET_RESPONSE(&xbdi->xbdi_ring.ring_64,
1498 xbdi->xbdi_ring.ring_n.rsp_prod_pvt); 1498 xbdi->xbdi_ring.ring_n.rsp_prod_pvt);
1499 resp64->id = id; 1499 resp64->id = id;
1500 resp64->operation = op; 1500 resp64->operation = op;
1501 resp64->status = status; 1501 resp64->status = status;
1502 break; 1502 break;
1503 } 1503 }
1504 xbdi->xbdi_ring.ring_n.rsp_prod_pvt++; 1504 xbdi->xbdi_ring.ring_n.rsp_prod_pvt++;
1505 RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&xbdi->xbdi_ring.ring_n, notify); 1505 RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&xbdi->xbdi_ring.ring_n, notify);
1506 if (notify) { 1506 if (notify) {
1507 XENPRINTF(("xbdback_send_reply notify %d\n", xbdi->xbdi_domid)); 1507 XENPRINTF(("xbdback_send_reply notify %d\n", xbdi->xbdi_domid));
1508 hypervisor_notify_via_evtchn(xbdi->xbdi_evtchn); 1508 hypervisor_notify_via_evtchn(xbdi->xbdi_evtchn);
1509 } 1509 }
1510} 1510}
1511 1511
1512/* 1512/*
1513 * Map a request into our virtual address space. The xbd_req->rq_ma 1513 * Map a request into our virtual address space. The xbd_req->rq_ma
1514 * array is to be filled out by the caller. 1514 * array is to be filled out by the caller.
1515 */ 1515 */
1516static void * 1516static void *
1517xbdback_map_shm(struct xbdback_io *xbd_io) 1517xbdback_map_shm(struct xbdback_io *xbd_io)
1518{ 1518{
1519 struct xbdback_instance *xbdi; 1519 struct xbdback_instance *xbdi;
1520 struct xbdback_request *xbd_rq; 1520 struct xbdback_request *xbd_rq;
1521 int error, s; 1521 int error, s;
1522 1522
1523#ifdef XENDEBUG_VBD 1523#ifdef XENDEBUG_VBD
1524 int i; 1524 int i;
1525 printf("xbdback_map_shm map grant "); 1525 printf("xbdback_map_shm map grant ");
1526 for (i = 0; i < xbd_io->xio_nrma; i++) { 1526 for (i = 0; i < xbd_io->xio_nrma; i++) {
1527 printf("%u ", (u_int)xbd_io->xio_gref[i]); 1527 printf("%u ", (u_int)xbd_io->xio_gref[i]);
1528 } 1528 }
1529#endif 1529#endif
1530 1530
1531 KASSERT(xbd_io->xio_mapped == 0); 1531 KASSERT(xbd_io->xio_mapped == 0);
1532 1532
1533 xbdi = xbd_io->xio_xbdi; 1533 xbdi = xbd_io->xio_xbdi;
1534 xbd_rq = SLIST_FIRST(&xbd_io->xio_rq)->car; 1534 xbd_rq = SLIST_FIRST(&xbd_io->xio_rq)->car;
1535 error = xen_shm_map(xbd_io->xio_nrma, xbdi->xbdi_domid, 1535 error = xen_shm_map(xbd_io->xio_nrma, xbdi->xbdi_domid,
1536 xbd_io->xio_gref, &xbd_io->xio_vaddr, xbd_io->xio_gh,  1536 xbd_io->xio_gref, &xbd_io->xio_vaddr, xbd_io->xio_gh,
1537 (xbd_rq->rq_operation == BLKIF_OP_WRITE) ? XSHM_RO: 0); 1537 (xbd_rq->rq_operation == BLKIF_OP_WRITE) ? XSHM_RO: 0);
1538 1538
1539 switch(error) { 1539 switch(error) {
1540 case 0: 1540 case 0:
1541#ifdef XENDEBUG_VBD 1541#ifdef XENDEBUG_VBD
1542 printf("handle "); 1542 printf("handle ");
1543 for (i = 0; i < xbd_io->xio_nrma; i++) { 1543 for (i = 0; i < xbd_io->xio_nrma; i++) {
1544 printf("%u ", (u_int)xbd_io->xio_gh[i]); 1544 printf("%u ", (u_int)xbd_io->xio_gh[i]);
1545 } 1545 }
1546 printf("\n"); 1546 printf("\n");
1547#endif 1547#endif
1548 xbd_io->xio_mapped = 1; 1548 xbd_io->xio_mapped = 1;
1549 return (void *)xbd_io->xio_vaddr; 1549 return (void *)xbd_io->xio_vaddr;
1550 case ENOMEM: 1550 case ENOMEM:
1551 s = splvm(); 1551 s = splvm();
1552 if (!xbdback_shmcb) { 1552 if (!xbdback_shmcb) {
1553 if (xen_shm_callback(xbdback_shm_callback, xbdi) 1553 if (xen_shm_callback(xbdback_shm_callback, xbdi)
1554 != 0) { 1554 != 0) {
1555 splx(s); 1555 splx(s);
1556 panic("xbdback_map_shm: " 1556 panic("xbdback_map_shm: "
1557 "xen_shm_callback failed"); 1557 "xen_shm_callback failed");
1558 } 1558 }
1559 xbdback_shmcb = 1; 1559 xbdback_shmcb = 1;
1560 } 1560 }
1561 SIMPLEQ_INSERT_TAIL(&xbdback_shmq, xbdi, xbdi_on_hold); 1561 SIMPLEQ_INSERT_TAIL(&xbdback_shmq, xbdi, xbdi_on_hold);
1562 splx(s); 1562 splx(s);
1563 return NULL; 1563 return NULL;
1564 default: 1564 default:
1565 printf("xbdback_map_shm: xen_shm error %d ", 1565 printf("xbdback_map_shm: xen_shm error %d ",
1566 error); 1566 error);
1567 xbdback_io_error(xbdi->xbdi_io, error); 1567 xbdback_io_error(xbdi->xbdi_io, error);
1568 xbdi->xbdi_io = NULL; 1568 xbdi->xbdi_io = NULL;
1569 xbdi->xbdi_cont = xbdi->xbdi_cont_aux; 1569 xbdi->xbdi_cont = xbdi->xbdi_cont_aux;
1570 return xbdi; 1570 return xbdi;
1571 } 1571 }
1572} 1572}
1573 1573
1574static int 1574static int
1575xbdback_shm_callback(void *arg) 1575xbdback_shm_callback(void *arg)
1576{ 1576{
1577 int error, s; 1577 int error, s;
1578 1578
1579 s = splvm(); 1579 s = splvm();
1580 while(!SIMPLEQ_EMPTY(&xbdback_shmq)) { 1580 while(!SIMPLEQ_EMPTY(&xbdback_shmq)) {
1581 struct xbdback_instance *xbdi; 1581 struct xbdback_instance *xbdi;
1582 struct xbdback_io *xbd_io; 1582 struct xbdback_io *xbd_io;
1583 struct xbdback_request *xbd_rq; 1583 struct xbdback_request *xbd_rq;
1584  1584
1585 xbdi = SIMPLEQ_FIRST(&xbdback_shmq); 1585 xbdi = SIMPLEQ_FIRST(&xbdback_shmq);
1586 xbd_io = xbdi->xbdi_io; 1586 xbd_io = xbdi->xbdi_io;
1587 xbd_rq = SLIST_FIRST(&xbd_io->xio_rq)->car; 1587 xbd_rq = SLIST_FIRST(&xbd_io->xio_rq)->car;
1588 KASSERT(xbd_io->xio_mapped == 0); 1588 KASSERT(xbd_io->xio_mapped == 0);
1589  1589
1590 error = xen_shm_map(xbd_io->xio_nrma, 1590 error = xen_shm_map(xbd_io->xio_nrma,
1591 xbdi->xbdi_domid, xbd_io->xio_gref, 1591 xbdi->xbdi_domid, xbd_io->xio_gref,
1592 &xbd_io->xio_vaddr, xbd_io->xio_gh,  1592 &xbd_io->xio_vaddr, xbd_io->xio_gh,
1593 XSHM_CALLBACK | 1593 XSHM_CALLBACK |
1594 ((xbd_rq->rq_operation == BLKIF_OP_WRITE) ? XSHM_RO: 0)); 1594 ((xbd_rq->rq_operation == BLKIF_OP_WRITE) ? XSHM_RO: 0));
1595 switch(error) { 1595 switch(error) {
1596 case ENOMEM: 1596 case ENOMEM: